xref: /libCEED/tests/t319-basis.c (revision 2b730f8b5a9c809740a0b3b302db43a719c636b1)
114556e63SJeremy L Thompson /// @file
214556e63SJeremy L Thompson /// Test projection interp and grad in multiple dimensions
314556e63SJeremy L Thompson /// \test Test projection interp and grad in multiple dimensions
414556e63SJeremy L Thompson #include <ceed.h>
514556e63SJeremy L Thompson #include <math.h>
614556e63SJeremy L Thompson 
714556e63SJeremy L Thompson static CeedScalar Eval(CeedInt dim, const CeedScalar x[]) {
814556e63SJeremy L Thompson   CeedScalar result = (x[0] + 0.1) * (x[0] + 0.1);
914556e63SJeremy L Thompson   if (dim > 1) result += (x[1] + 0.2) * (x[1] + 0.2);
1014556e63SJeremy L Thompson   if (dim > 2) result += -(x[2] + 0.3) * (x[2] + 0.3);
1114556e63SJeremy L Thompson   return result;
1214556e63SJeremy L Thompson }
1314556e63SJeremy L Thompson 
1414556e63SJeremy L Thompson static CeedScalar EvalGrad(CeedInt dim, const CeedScalar x[]) {
1514556e63SJeremy L Thompson   switch (dim) {
16*2b730f8bSJeremy L Thompson     case 0:
17*2b730f8bSJeremy L Thompson       return 2 * x[0] + 0.2;
18*2b730f8bSJeremy L Thompson     case 1:
19*2b730f8bSJeremy L Thompson       return 2 * x[1] + 0.4;
20*2b730f8bSJeremy L Thompson     default:
21*2b730f8bSJeremy L Thompson       return -2 * x[2] - 0.6;
2214556e63SJeremy L Thompson   }
2314556e63SJeremy L Thompson }
2414556e63SJeremy L Thompson 
2514556e63SJeremy L Thompson static CeedScalar GetTolerance(CeedScalarType scalar_type, int dim) {
2614556e63SJeremy L Thompson   CeedScalar tol;
2714556e63SJeremy L Thompson   if (scalar_type == CEED_SCALAR_FP32) {
28*2b730f8bSJeremy L Thompson     if (dim == 3) tol = 1.e-4;
29*2b730f8bSJeremy L Thompson     else tol = 1.e-5;
3014556e63SJeremy L Thompson   } else {
3114556e63SJeremy L Thompson     tol = 1.e-11;
3214556e63SJeremy L Thompson   }
3314556e63SJeremy L Thompson   return tol;
3414556e63SJeremy L Thompson }
3514556e63SJeremy L Thompson 
3614556e63SJeremy L Thompson int main(int argc, char **argv) {
3714556e63SJeremy L Thompson   Ceed ceed;
3814556e63SJeremy L Thompson 
3914556e63SJeremy L Thompson   CeedInit(argv[1], &ceed);
4014556e63SJeremy L Thompson 
4114556e63SJeremy L Thompson   for (CeedInt dim = 1; dim <= 3; dim++) {
4214556e63SJeremy L Thompson     CeedVector        X_corners, X_from, X_to, U_from, U_to, dU_to;
4314556e63SJeremy L Thompson     CeedBasis         basis_x, basis_from, basis_to, basis_project;
44*2b730f8bSJeremy L Thompson     CeedInt           P_from = 5, P_to = 6, Q = 7, X_dim = CeedIntPow(2, dim), P_from_dim = CeedIntPow(P_from, dim), P_to_dim = CeedIntPow(P_to, dim);
4514556e63SJeremy L Thompson     CeedScalar        x[X_dim * dim], u_from[P_from_dim];
4614556e63SJeremy L Thompson     const CeedScalar *u_to, *du_to, *x_from, *x_to;
4714556e63SJeremy L Thompson 
48*2b730f8bSJeremy L Thompson     for (CeedInt d = 0; d < dim; d++) {
49*2b730f8bSJeremy L Thompson       for (CeedInt i = 0; i < X_dim; i++) x[X_dim * d + i] = (i % CeedIntPow(2, dim - d)) / CeedIntPow(2, dim - d - 1) ? 1 : -1;
50*2b730f8bSJeremy L Thompson     }
5114556e63SJeremy L Thompson 
5214556e63SJeremy L Thompson     CeedVectorCreate(ceed, X_dim * dim, &X_corners);
5314556e63SJeremy L Thompson     CeedVectorSetArray(X_corners, CEED_MEM_HOST, CEED_USE_POINTER, x);
5414556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_from_dim * dim, &X_from);
5514556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_to_dim * dim, &X_to);
5614556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_from_dim, &U_from);
5714556e63SJeremy L Thompson     CeedVectorSetValue(U_from, 0);
5814556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_to_dim, &U_to);
5914556e63SJeremy L Thompson     CeedVectorSetValue(U_to, 0);
6014556e63SJeremy L Thompson     CeedVectorCreate(ceed, P_to_dim * dim, &dU_to);
6114556e63SJeremy L Thompson     CeedVectorSetValue(dU_to, 0);
6214556e63SJeremy L Thompson 
6314556e63SJeremy L Thompson     // Get nodal coordinates
64*2b730f8bSJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, P_from, CEED_GAUSS_LOBATTO, &basis_x);
65*2b730f8bSJeremy L Thompson     CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, X_corners, X_from);
6614556e63SJeremy L Thompson     CeedBasisDestroy(&basis_x);
67*2b730f8bSJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, P_to, CEED_GAUSS_LOBATTO, &basis_x);
6814556e63SJeremy L Thompson     CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, X_corners, X_to);
6914556e63SJeremy L Thompson     CeedBasisDestroy(&basis_x);
7014556e63SJeremy L Thompson 
7114556e63SJeremy L Thompson     // Create U and projection bases
72*2b730f8bSJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P_from, Q, CEED_GAUSS, &basis_from);
7314556e63SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P_to, Q, CEED_GAUSS, &basis_to);
7414556e63SJeremy L Thompson     CeedBasisCreateProjection(basis_from, basis_to, &basis_project);
7514556e63SJeremy L Thompson 
7614556e63SJeremy L Thompson     // Setup coarse solution
7714556e63SJeremy L Thompson     CeedVectorGetArrayRead(X_from, CEED_MEM_HOST, &x_from);
7814556e63SJeremy L Thompson     for (CeedInt i = 0; i < P_from_dim; i++) {
7914556e63SJeremy L Thompson       CeedScalar xx[dim];
8014556e63SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) xx[d] = x_from[P_from_dim * d + i];
8114556e63SJeremy L Thompson       u_from[i] = Eval(dim, xx);
8214556e63SJeremy L Thompson     }
8314556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(X_from, &x_from);
8414556e63SJeremy L Thompson     CeedVectorSetArray(U_from, CEED_MEM_HOST, CEED_USE_POINTER, u_from);
8514556e63SJeremy L Thompson 
8614556e63SJeremy L Thompson     // Project to fine basis
87*2b730f8bSJeremy L Thompson     CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, U_from, U_to);
8814556e63SJeremy L Thompson 
8914556e63SJeremy L Thompson     // Check solution
9014556e63SJeremy L Thompson     CeedVectorGetArrayRead(U_to, CEED_MEM_HOST, &u_to);
9114556e63SJeremy L Thompson     CeedVectorGetArrayRead(X_to, CEED_MEM_HOST, &x_to);
9214556e63SJeremy L Thompson     CeedScalar tol = GetTolerance(CEED_SCALAR_TYPE, dim);
9314556e63SJeremy L Thompson     for (CeedInt i = 0; i < P_to_dim; i++) {
9414556e63SJeremy L Thompson       CeedScalar xx[dim];
9514556e63SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) xx[d] = x_to[d * P_to_dim + i];
9614556e63SJeremy L Thompson       const CeedScalar u = Eval(dim, xx);
97*2b730f8bSJeremy L Thompson       if (fabs(u - u_to[i]) > tol) printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, u_to[i], u);
9814556e63SJeremy L Thompson     }
9914556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(X_to, &x_to);
10014556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(U_to, &u_to);
10114556e63SJeremy L Thompson 
10214556e63SJeremy L Thompson     // Project and take gradient
103*2b730f8bSJeremy L Thompson     CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, U_from, dU_to);
10414556e63SJeremy L Thompson 
10514556e63SJeremy L Thompson     // Check solution
10614556e63SJeremy L Thompson     CeedVectorGetArrayRead(dU_to, CEED_MEM_HOST, &du_to);
10714556e63SJeremy L Thompson     CeedVectorGetArrayRead(X_to, CEED_MEM_HOST, &x_to);
10814556e63SJeremy L Thompson     for (CeedInt i = 0; i < P_to_dim; i++) {
10914556e63SJeremy L Thompson       CeedScalar xx[dim];
11014556e63SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) xx[d] = x_to[P_to_dim * d + i];
11114556e63SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) {
11214556e63SJeremy L Thompson         const CeedScalar du = EvalGrad(d, xx);
113*2b730f8bSJeremy L Thompson         if (fabs(du - du_to[P_to_dim * (dim - 1 - d) + i]) > tol) {
11414556e63SJeremy L Thompson           // LCOV_EXCL_START
115*2b730f8bSJeremy L Thompson           printf("[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, d, du_to[P_to_dim * (dim - 1 - d) + i], du);
11614556e63SJeremy L Thompson           // LCOV_EXCL_STOP
11714556e63SJeremy L Thompson         }
11814556e63SJeremy L Thompson       }
119*2b730f8bSJeremy L Thompson     }
12014556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(X_to, &x_to);
12114556e63SJeremy L Thompson     CeedVectorRestoreArrayRead(dU_to, &du_to);
12214556e63SJeremy L Thompson 
12314556e63SJeremy L Thompson     CeedVectorDestroy(&X_corners);
12414556e63SJeremy L Thompson     CeedVectorDestroy(&X_from);
12514556e63SJeremy L Thompson     CeedVectorDestroy(&X_to);
12614556e63SJeremy L Thompson     CeedVectorDestroy(&U_from);
12714556e63SJeremy L Thompson     CeedVectorDestroy(&U_to);
12814556e63SJeremy L Thompson     CeedVectorDestroy(&dU_to);
12914556e63SJeremy L Thompson     CeedBasisDestroy(&basis_from);
13014556e63SJeremy L Thompson     CeedBasisDestroy(&basis_to);
13114556e63SJeremy L Thompson     CeedBasisDestroy(&basis_project);
13214556e63SJeremy L Thompson   }
13314556e63SJeremy L Thompson   CeedDestroy(&ceed);
13414556e63SJeremy L Thompson   return 0;
13514556e63SJeremy L Thompson }
136