xref: /libCEED/tests/t319-basis.c (revision 097cc79570fc1ccd17774d2bf9cd5e51d3925370)
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>
649aac155SJeremy L Thompson #include <stdio.h>
714556e63SJeremy L Thompson 
814556e63SJeremy L Thompson static CeedScalar Eval(CeedInt dim, const CeedScalar x[]) {
914556e63SJeremy L Thompson   CeedScalar result = (x[0] + 0.1) * (x[0] + 0.1);
1014556e63SJeremy L Thompson   if (dim > 1) result += (x[1] + 0.2) * (x[1] + 0.2);
1114556e63SJeremy L Thompson   if (dim > 2) result += -(x[2] + 0.3) * (x[2] + 0.3);
1214556e63SJeremy L Thompson   return result;
1314556e63SJeremy L Thompson }
1414556e63SJeremy L Thompson 
1514556e63SJeremy L Thompson static CeedScalar EvalGrad(CeedInt dim, const CeedScalar x[]) {
1614556e63SJeremy L Thompson   switch (dim) {
172b730f8bSJeremy L Thompson     case 0:
182b730f8bSJeremy L Thompson       return 2 * x[0] + 0.2;
192b730f8bSJeremy L Thompson     case 1:
202b730f8bSJeremy L Thompson       return 2 * x[1] + 0.4;
212b730f8bSJeremy L Thompson     default:
222b730f8bSJeremy L Thompson       return -2 * x[2] - 0.6;
2314556e63SJeremy L Thompson   }
2414556e63SJeremy L Thompson }
2514556e63SJeremy L Thompson 
2614556e63SJeremy L Thompson static CeedScalar GetTolerance(CeedScalarType scalar_type, int dim) {
2714556e63SJeremy L Thompson   CeedScalar tol;
2814556e63SJeremy L Thompson   if (scalar_type == CEED_SCALAR_FP32) {
292b730f8bSJeremy L Thompson     if (dim == 3) tol = 1.e-4;
302b730f8bSJeremy L Thompson     else tol = 1.e-5;
3114556e63SJeremy L Thompson   } else {
3214556e63SJeremy L Thompson     tol = 1.e-11;
3314556e63SJeremy L Thompson   }
3414556e63SJeremy L Thompson   return tol;
3514556e63SJeremy L Thompson }
3614556e63SJeremy L Thompson 
37*097cc795SJames Wright static void VerifyProjectedBasis(CeedBasis basis_project, CeedInt dim, CeedInt p_to_dim, CeedInt p_from_dim, CeedVector x_to, CeedVector x_from,
38*097cc795SJames Wright                                  CeedVector u_to, CeedVector u_from, CeedVector du_to) {
3999e754f0SJeremy L Thompson   CeedScalar tol;
404fee36f0SJeremy L Thompson 
4199e754f0SJeremy L Thompson   {
4299e754f0SJeremy L Thompson     CeedScalarType scalar_type;
4399e754f0SJeremy L Thompson 
4499e754f0SJeremy L Thompson     CeedGetScalarType(&scalar_type);
4599e754f0SJeremy L Thompson     tol = GetTolerance(scalar_type, dim);
4699e754f0SJeremy L Thompson   }
4714556e63SJeremy L Thompson 
4814556e63SJeremy L Thompson   // Setup coarse solution
494fee36f0SJeremy L Thompson   {
504fee36f0SJeremy L Thompson     const CeedScalar *x_array;
514fee36f0SJeremy L Thompson     CeedScalar        u_array[p_from_dim];
524fee36f0SJeremy L Thompson 
534fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(x_from, CEED_MEM_HOST, &x_array);
544fee36f0SJeremy L Thompson     for (CeedInt i = 0; i < p_from_dim; i++) {
554fee36f0SJeremy L Thompson       CeedScalar coord[dim];
564fee36f0SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[p_from_dim * d + i];
574fee36f0SJeremy L Thompson       u_array[i] = Eval(dim, coord);
5814556e63SJeremy L Thompson     }
594fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(x_from, &x_array);
604fee36f0SJeremy L Thompson     CeedVectorSetArray(u_from, CEED_MEM_HOST, CEED_COPY_VALUES, u_array);
614fee36f0SJeremy L Thompson   }
6214556e63SJeremy L Thompson 
6314556e63SJeremy L Thompson   // Project to fine basis
644fee36f0SJeremy L Thompson   CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, u_from, u_to);
6514556e63SJeremy L Thompson 
6614556e63SJeremy L Thompson   // Check solution
674fee36f0SJeremy L Thompson   {
684fee36f0SJeremy L Thompson     const CeedScalar *x_array, *u_array;
694fee36f0SJeremy L Thompson 
704fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(x_to, CEED_MEM_HOST, &x_array);
714fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(u_to, CEED_MEM_HOST, &u_array);
724fee36f0SJeremy L Thompson     for (CeedInt i = 0; i < p_to_dim; i++) {
734fee36f0SJeremy L Thompson       CeedScalar coord[dim];
744fee36f0SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[d * p_to_dim + i];
754fee36f0SJeremy L Thompson       const CeedScalar u = Eval(dim, coord);
764fee36f0SJeremy L Thompson       if (fabs(u - u_array[i]) > tol) printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, u_array[i], u);
7714556e63SJeremy L Thompson     }
784fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(x_to, &x_array);
794fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(u_to, &u_array);
804fee36f0SJeremy L Thompson   }
8114556e63SJeremy L Thompson 
8214556e63SJeremy L Thompson   // Project and take gradient
834fee36f0SJeremy L Thompson   CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, u_from, du_to);
8414556e63SJeremy L Thompson 
8514556e63SJeremy L Thompson   // Check solution
864fee36f0SJeremy L Thompson   {
874fee36f0SJeremy L Thompson     const CeedScalar *x_array, *du_array;
884fee36f0SJeremy L Thompson 
894fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(x_to, CEED_MEM_HOST, &x_array);
904fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(du_to, CEED_MEM_HOST, &du_array);
914fee36f0SJeremy L Thompson     for (CeedInt i = 0; i < p_to_dim; i++) {
924fee36f0SJeremy L Thompson       CeedScalar coord[dim];
9399e754f0SJeremy L Thompson 
944fee36f0SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[p_to_dim * d + i];
9514556e63SJeremy L Thompson       for (CeedInt d = 0; d < dim; d++) {
964fee36f0SJeremy L Thompson         const CeedScalar du = EvalGrad(d, coord);
9799e754f0SJeremy L Thompson 
983c9d155aSZach Atkins         if (fabs(du - du_array[p_to_dim * d + i]) > tol) {
9914556e63SJeremy L Thompson           // LCOV_EXCL_START
1004fee36f0SJeremy L Thompson           printf("[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, d, du_array[p_to_dim * (dim - 1 - d) + i], du);
10114556e63SJeremy L Thompson           // LCOV_EXCL_STOP
10214556e63SJeremy L Thompson         }
10314556e63SJeremy L Thompson       }
1042b730f8bSJeremy L Thompson     }
1054fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(x_to, &x_array);
1064fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(du_to, &du_array);
1074fee36f0SJeremy L Thompson   }
108*097cc795SJames Wright }
109*097cc795SJames Wright 
110*097cc795SJames Wright int main(int argc, char **argv) {
111*097cc795SJames Wright   Ceed ceed;
112*097cc795SJames Wright 
113*097cc795SJames Wright   CeedInit(argv[1], &ceed);
114*097cc795SJames Wright 
115*097cc795SJames Wright   for (CeedInt dim = 1; dim <= 3; dim++) {
116*097cc795SJames Wright     CeedVector x_corners, x_from, x_to, u_from, u_to, du_to;
117*097cc795SJames Wright     CeedBasis  basis_x, basis_from, basis_to, basis_project;
118*097cc795SJames Wright     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);
119*097cc795SJames Wright 
120*097cc795SJames Wright     CeedVectorCreate(ceed, x_dim * dim, &x_corners);
121*097cc795SJames Wright     {
122*097cc795SJames Wright       CeedScalar x_array[x_dim * dim];
123*097cc795SJames Wright 
124*097cc795SJames Wright       for (CeedInt d = 0; d < dim; d++) {
125*097cc795SJames Wright         for (CeedInt i = 0; i < x_dim; i++) x_array[x_dim * d + i] = (i % CeedIntPow(2, d + 1)) / CeedIntPow(2, d) ? 1 : -1;
126*097cc795SJames Wright       }
127*097cc795SJames Wright       CeedVectorSetArray(x_corners, CEED_MEM_HOST, CEED_COPY_VALUES, x_array);
128*097cc795SJames Wright     }
129*097cc795SJames Wright     CeedVectorCreate(ceed, p_from_dim * dim, &x_from);
130*097cc795SJames Wright     CeedVectorCreate(ceed, p_to_dim * dim, &x_to);
131*097cc795SJames Wright     CeedVectorCreate(ceed, p_from_dim, &u_from);
132*097cc795SJames Wright     CeedVectorSetValue(u_from, 0);
133*097cc795SJames Wright     CeedVectorCreate(ceed, p_to_dim, &u_to);
134*097cc795SJames Wright     CeedVectorSetValue(u_to, 0);
135*097cc795SJames Wright     CeedVectorCreate(ceed, p_to_dim * dim, &du_to);
136*097cc795SJames Wright     CeedVectorSetValue(du_to, 0);
137*097cc795SJames Wright 
138*097cc795SJames Wright     // Get nodal coordinates
139*097cc795SJames Wright     CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, p_from, CEED_GAUSS_LOBATTO, &basis_x);
140*097cc795SJames Wright     CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, x_corners, x_from);
141*097cc795SJames Wright     CeedBasisDestroy(&basis_x);
142*097cc795SJames Wright     CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, p_to, CEED_GAUSS_LOBATTO, &basis_x);
143*097cc795SJames Wright     CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, x_corners, x_to);
144*097cc795SJames Wright     CeedBasisDestroy(&basis_x);
145*097cc795SJames Wright 
146*097cc795SJames Wright     // Create U and projection bases
147*097cc795SJames Wright     CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p_from, q, CEED_GAUSS, &basis_from);
148*097cc795SJames Wright     CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p_to, q, CEED_GAUSS, &basis_to);
149*097cc795SJames Wright     CeedBasisCreateProjection(basis_from, basis_to, &basis_project);
150*097cc795SJames Wright 
151*097cc795SJames Wright     VerifyProjectedBasis(basis_project, dim, p_to_dim, p_from_dim, x_to, x_from, u_to, u_from, du_to);
152*097cc795SJames Wright 
153*097cc795SJames Wright     // Test projection on non-tensor bases
154*097cc795SJames Wright     {
155*097cc795SJames Wright       CeedBasis         basis_from_nontensor, basis_to_nontensor;
156*097cc795SJames Wright       CeedElemTopology  topo;
157*097cc795SJames Wright       CeedInt           num_comp, num_nodes, nqpts;
158*097cc795SJames Wright       const CeedScalar *interp, *grad;
159*097cc795SJames Wright 
160*097cc795SJames Wright       CeedBasisGetTopology(basis_from, &topo);
161*097cc795SJames Wright       CeedBasisGetNumComponents(basis_from, &num_comp);
162*097cc795SJames Wright       CeedBasisGetNumNodes(basis_from, &num_nodes);
163*097cc795SJames Wright       CeedBasisGetNumQuadraturePoints(basis_from, &nqpts);
164*097cc795SJames Wright       CeedBasisGetInterp(basis_from, &interp);
165*097cc795SJames Wright       CeedBasisGetGrad(basis_from, &grad);
166*097cc795SJames Wright       CeedBasisCreateH1(ceed, topo, num_comp, num_nodes, nqpts, interp, grad, NULL, NULL, &basis_from_nontensor);
167*097cc795SJames Wright 
168*097cc795SJames Wright       CeedBasisGetTopology(basis_to, &topo);
169*097cc795SJames Wright       CeedBasisGetNumComponents(basis_to, &num_comp);
170*097cc795SJames Wright       CeedBasisGetNumNodes(basis_to, &num_nodes);
171*097cc795SJames Wright       CeedBasisGetNumQuadraturePoints(basis_to, &nqpts);
172*097cc795SJames Wright       CeedBasisGetInterp(basis_to, &interp);
173*097cc795SJames Wright       CeedBasisGetGrad(basis_to, &grad);
174*097cc795SJames Wright       CeedBasisCreateH1(ceed, topo, num_comp, num_nodes, nqpts, interp, grad, NULL, NULL, &basis_to_nontensor);
175*097cc795SJames Wright 
176*097cc795SJames Wright       CeedBasisDestroy(&basis_project);
177*097cc795SJames Wright       CeedBasisCreateProjection(basis_from_nontensor, basis_to_nontensor, &basis_project);
178*097cc795SJames Wright 
179*097cc795SJames Wright       CeedBasisDestroy(&basis_to_nontensor);
180*097cc795SJames Wright       CeedBasisDestroy(&basis_from_nontensor);
181*097cc795SJames Wright     }
182*097cc795SJames Wright 
183*097cc795SJames Wright     VerifyProjectedBasis(basis_project, dim, p_to_dim, p_from_dim, x_to, x_from, u_to, u_from, du_to);
18414556e63SJeremy L Thompson 
1854fee36f0SJeremy L Thompson     CeedVectorDestroy(&x_corners);
1864fee36f0SJeremy L Thompson     CeedVectorDestroy(&x_from);
1874fee36f0SJeremy L Thompson     CeedVectorDestroy(&x_to);
1884fee36f0SJeremy L Thompson     CeedVectorDestroy(&u_from);
1894fee36f0SJeremy L Thompson     CeedVectorDestroy(&u_to);
1904fee36f0SJeremy L Thompson     CeedVectorDestroy(&du_to);
19114556e63SJeremy L Thompson     CeedBasisDestroy(&basis_from);
19214556e63SJeremy L Thompson     CeedBasisDestroy(&basis_to);
19314556e63SJeremy L Thompson     CeedBasisDestroy(&basis_project);
19414556e63SJeremy L Thompson   }
19514556e63SJeremy L Thompson   CeedDestroy(&ceed);
19614556e63SJeremy L Thompson   return 0;
19714556e63SJeremy L Thompson }
198