xref: /libCEED/tests/t319-basis.c (revision 14556e6313a53166f141434c5f96b2c98b83e854)
1*14556e63SJeremy L Thompson /// @file
2*14556e63SJeremy L Thompson /// Test projection interp and grad in multiple dimensions
3*14556e63SJeremy L Thompson /// \test Test projection interp and grad in multiple dimensions
4*14556e63SJeremy L Thompson #include <ceed.h>
5*14556e63SJeremy L Thompson #include <math.h>
6*14556e63SJeremy L Thompson 
7*14556e63SJeremy L Thompson static CeedScalar Eval(CeedInt dim, const CeedScalar x[]) {
8*14556e63SJeremy L Thompson   CeedScalar result = (x[0] + 0.1) * (x[0] + 0.1);
9*14556e63SJeremy L Thompson   if (dim > 1) result += (x[1] + 0.2) * (x[1] + 0.2);
10*14556e63SJeremy L Thompson   if (dim > 2) result += -(x[2] + 0.3) * (x[2] + 0.3);
11*14556e63SJeremy L Thompson   return result;
12*14556e63SJeremy L Thompson }
13*14556e63SJeremy L Thompson 
14*14556e63SJeremy L Thompson static CeedScalar EvalGrad(CeedInt dim, const CeedScalar x[]) {
15*14556e63SJeremy L Thompson   switch (dim) {
16*14556e63SJeremy L Thompson   case 0: return 2 * x[0] + 0.2;
17*14556e63SJeremy L Thompson   case 1: return 2 * x[1] + 0.4;
18*14556e63SJeremy L Thompson   default: return -2 * x[2] - 0.6;
19*14556e63SJeremy L Thompson   }
20*14556e63SJeremy L Thompson }
21*14556e63SJeremy L Thompson 
22*14556e63SJeremy L Thompson static CeedScalar GetTolerance(CeedScalarType scalar_type, int dim) {
23*14556e63SJeremy L Thompson   CeedScalar tol;
24*14556e63SJeremy L Thompson   if (scalar_type == CEED_SCALAR_FP32) {
25*14556e63SJeremy L Thompson     if (dim == 3)
26*14556e63SJeremy L Thompson       tol = 1.e-4;
27*14556e63SJeremy L Thompson     else
28*14556e63SJeremy L Thompson       tol = 1.e-5;
29*14556e63SJeremy L Thompson   } else {
30*14556e63SJeremy L Thompson     tol = 1.e-11;
31*14556e63SJeremy L Thompson   }
32*14556e63SJeremy L Thompson   return tol;
33*14556e63SJeremy L Thompson }
34*14556e63SJeremy L Thompson 
35*14556e63SJeremy L Thompson int main(int argc, char **argv) {
36*14556e63SJeremy L Thompson   Ceed ceed;
37*14556e63SJeremy L Thompson 
38*14556e63SJeremy L Thompson   CeedInit(argv[1], &ceed);
39*14556e63SJeremy L Thompson 
40*14556e63SJeremy L Thompson   for (CeedInt dim = 1; dim <= 3; dim++) {
41*14556e63SJeremy L Thompson     CeedVector X_corners, X_from, X_to, U_from, U_to, dU_to;
42*14556e63SJeremy L Thompson     CeedBasis basis_x, basis_from, basis_to, basis_project;
43*14556e63SJeremy L Thompson     CeedInt P_from = 5, P_to = 6, Q = 7, X_dim = CeedIntPow(2, dim),
44*14556e63SJeremy L Thompson             P_from_dim = CeedIntPow(P_from, dim), P_to_dim = CeedIntPow(P_to, dim);
45*14556e63SJeremy L Thompson     CeedScalar x[X_dim * dim], u_from[P_from_dim];
46*14556e63SJeremy L Thompson     const CeedScalar *u_to, *du_to, *x_from, *x_to;
47*14556e63SJeremy L Thompson 
48*14556e63SJeremy L Thompson     for (CeedInt d=0; d<dim; d++)
49*14556e63SJeremy L Thompson       for (CeedInt i=0; i<X_dim; i++)
50*14556e63SJeremy L Thompson         x[X_dim * d + i] = (i % CeedIntPow(2, dim-d)) /
51*14556e63SJeremy L Thompson                            CeedIntPow(2, dim-d-1) ? 1 : -1;
52*14556e63SJeremy L Thompson 
53*14556e63SJeremy L Thompson     CeedVectorCreate(ceed, X_dim * dim, &X_corners);
54*14556e63SJeremy L Thompson     CeedVectorSetArray(X_corners, CEED_MEM_HOST, CEED_USE_POINTER, x);
55*14556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_from_dim * dim, &X_from);
56*14556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_to_dim * dim, &X_to);
57*14556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_from_dim, &U_from);
58*14556e63SJeremy L Thompson     CeedVectorSetValue(U_from, 0);
59*14556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_to_dim, &U_to);
60*14556e63SJeremy L Thompson     CeedVectorSetValue(U_to, 0);
61*14556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_to_dim * dim, &dU_to);
62*14556e63SJeremy L Thompson     CeedVectorSetValue(dU_to, 0);
63*14556e63SJeremy L Thompson 
64*14556e63SJeremy L Thompson     // Get nodal coordinates
65*14556e63SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, P_from,
66*14556e63SJeremy L Thompson                                     CEED_GAUSS_LOBATTO, &basis_x);
67*14556e63SJeremy L Thompson     CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, X_corners,
68*14556e63SJeremy L Thompson                    X_from);
69*14556e63SJeremy L Thompson     CeedBasisDestroy(&basis_x);
70*14556e63SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, P_to,
71*14556e63SJeremy L Thompson                                     CEED_GAUSS_LOBATTO, &basis_x);
72*14556e63SJeremy L Thompson     CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, X_corners, X_to);
73*14556e63SJeremy L Thompson     CeedBasisDestroy(&basis_x);
74*14556e63SJeremy L Thompson 
75*14556e63SJeremy L Thompson     // Create U and projection bases
76*14556e63SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P_from, Q, CEED_GAUSS,
77*14556e63SJeremy L Thompson                                     &basis_from);
78*14556e63SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P_to, Q, CEED_GAUSS, &basis_to);
79*14556e63SJeremy L Thompson     CeedBasisCreateProjection(basis_from, basis_to, &basis_project);
80*14556e63SJeremy L Thompson 
81*14556e63SJeremy L Thompson     // Setup coarse solution
82*14556e63SJeremy L Thompson     CeedVectorGetArrayRead(X_from, CEED_MEM_HOST, &x_from);
83*14556e63SJeremy L Thompson     for (CeedInt i=0; i<P_from_dim; i++) {
84*14556e63SJeremy L Thompson       CeedScalar xx[dim];
85*14556e63SJeremy L Thompson       for (CeedInt d=0; d<dim; d++) xx[d] = x_from[P_from_dim * d + i];
86*14556e63SJeremy L Thompson       u_from[i] = Eval(dim, xx);
87*14556e63SJeremy L Thompson     }
88*14556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(X_from, &x_from);
89*14556e63SJeremy L Thompson     CeedVectorSetArray(U_from, CEED_MEM_HOST, CEED_USE_POINTER, u_from);
90*14556e63SJeremy L Thompson 
91*14556e63SJeremy L Thompson     // Project to fine basis
92*14556e63SJeremy L Thompson     CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, U_from,
93*14556e63SJeremy L Thompson                    U_to);
94*14556e63SJeremy L Thompson 
95*14556e63SJeremy L Thompson     // Check solution
96*14556e63SJeremy L Thompson     CeedVectorGetArrayRead(U_to, CEED_MEM_HOST, &u_to);
97*14556e63SJeremy L Thompson     CeedVectorGetArrayRead(X_to, CEED_MEM_HOST, &x_to);
98*14556e63SJeremy L Thompson     CeedScalar tol = GetTolerance(CEED_SCALAR_TYPE, dim);
99*14556e63SJeremy L Thompson     for (CeedInt i=0; i<P_to_dim; i++) {
100*14556e63SJeremy L Thompson       CeedScalar xx[dim];
101*14556e63SJeremy L Thompson       for (CeedInt d=0; d<dim; d++) xx[d] = x_to[d*P_to_dim + i];
102*14556e63SJeremy L Thompson       const CeedScalar u = Eval(dim, xx);
103*14556e63SJeremy L Thompson       if (fabs(u - u_to[i]) > tol)
104*14556e63SJeremy L Thompson         // LCOV_EXCL_START
105*14556e63SJeremy L Thompson         printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, u_to[i], u);
106*14556e63SJeremy L Thompson       // LCOV_EXCL_STOP
107*14556e63SJeremy L Thompson     }
108*14556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(X_to, &x_to);
109*14556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(U_to, &u_to);
110*14556e63SJeremy L Thompson 
111*14556e63SJeremy L Thompson     // Project and take gradient
112*14556e63SJeremy L Thompson     CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, U_from,
113*14556e63SJeremy L Thompson                    dU_to);
114*14556e63SJeremy L Thompson 
115*14556e63SJeremy L Thompson     // Check solution
116*14556e63SJeremy L Thompson     CeedVectorGetArrayRead(dU_to, CEED_MEM_HOST, &du_to);
117*14556e63SJeremy L Thompson     CeedVectorGetArrayRead(X_to, CEED_MEM_HOST, &x_to);
118*14556e63SJeremy L Thompson     for (CeedInt i=0; i<P_to_dim; i++) {
119*14556e63SJeremy L Thompson       CeedScalar xx[dim];
120*14556e63SJeremy L Thompson       for (CeedInt d=0; d<dim; d++) xx[d] = x_to[P_to_dim * d + i];
121*14556e63SJeremy L Thompson       for (CeedInt d=0; d<dim; d++) {
122*14556e63SJeremy L Thompson         const CeedScalar du = EvalGrad(d, xx);
123*14556e63SJeremy L Thompson         if (fabs(du - du_to[P_to_dim * (dim - 1 - d) + i]) > tol)
124*14556e63SJeremy L Thompson           // LCOV_EXCL_START
125*14556e63SJeremy L Thompson           printf("[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim,
126*14556e63SJeremy L Thompson                  i, d, du_to[P_to_dim * (dim - 1 - d) + i], du);
127*14556e63SJeremy L Thompson         // LCOV_EXCL_STOP
128*14556e63SJeremy L Thompson       }
129*14556e63SJeremy L Thompson     }
130*14556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(X_to, &x_to);
131*14556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(dU_to, &du_to);
132*14556e63SJeremy L Thompson 
133*14556e63SJeremy L Thompson     CeedVectorDestroy(&X_corners);
134*14556e63SJeremy L Thompson     CeedVectorDestroy(&X_from);
135*14556e63SJeremy L Thompson     CeedVectorDestroy(&X_to);
136*14556e63SJeremy L Thompson     CeedVectorDestroy(&U_from);
137*14556e63SJeremy L Thompson     CeedVectorDestroy(&U_to);
138*14556e63SJeremy L Thompson     CeedVectorDestroy(&dU_to);
139*14556e63SJeremy L Thompson     CeedBasisDestroy(&basis_from);
140*14556e63SJeremy L Thompson     CeedBasisDestroy(&basis_to);
141*14556e63SJeremy L Thompson     CeedBasisDestroy(&basis_project);
142*14556e63SJeremy L Thompson   }
143*14556e63SJeremy L Thompson   CeedDestroy(&ceed);
144*14556e63SJeremy L Thompson   return 0;
145*14556e63SJeremy L Thompson }
146