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
4706bf528SJames Wright #include "t319-basis.h"
514556e63SJeremy L Thompson #include <ceed.h>
614556e63SJeremy L Thompson #include <math.h>
749aac155SJeremy L Thompson #include <stdio.h>
814556e63SJeremy L Thompson
Eval(CeedInt dim,const CeedScalar x[])914556e63SJeremy L Thompson static CeedScalar Eval(CeedInt dim, const CeedScalar x[]) {
1014556e63SJeremy L Thompson CeedScalar result = (x[0] + 0.1) * (x[0] + 0.1);
1114556e63SJeremy L Thompson if (dim > 1) result += (x[1] + 0.2) * (x[1] + 0.2);
1214556e63SJeremy L Thompson if (dim > 2) result += -(x[2] + 0.3) * (x[2] + 0.3);
1314556e63SJeremy L Thompson return result;
1414556e63SJeremy L Thompson }
1514556e63SJeremy L Thompson
EvalGrad(CeedInt dim,const CeedScalar x[])1614556e63SJeremy L Thompson static CeedScalar EvalGrad(CeedInt dim, const CeedScalar x[]) {
1714556e63SJeremy L Thompson switch (dim) {
182b730f8bSJeremy L Thompson case 0:
192b730f8bSJeremy L Thompson return 2 * x[0] + 0.2;
202b730f8bSJeremy L Thompson case 1:
212b730f8bSJeremy L Thompson return 2 * x[1] + 0.4;
222b730f8bSJeremy L Thompson default:
232b730f8bSJeremy L Thompson return -2 * x[2] - 0.6;
2414556e63SJeremy L Thompson }
2514556e63SJeremy L Thompson }
2614556e63SJeremy L Thompson
GetTolerance(CeedScalarType scalar_type,int dim)2714556e63SJeremy L Thompson static CeedScalar GetTolerance(CeedScalarType scalar_type, int dim) {
2814556e63SJeremy L Thompson CeedScalar tol;
2914556e63SJeremy L Thompson if (scalar_type == CEED_SCALAR_FP32) {
302b730f8bSJeremy L Thompson if (dim == 3) tol = 1.e-4;
312b730f8bSJeremy L Thompson else tol = 1.e-5;
3214556e63SJeremy L Thompson } else {
3314556e63SJeremy L Thompson tol = 1.e-11;
3414556e63SJeremy L Thompson }
3514556e63SJeremy L Thompson return tol;
3614556e63SJeremy L Thompson }
3714556e63SJeremy L Thompson
VerifyProjectedBasis(CeedBasis basis_project,CeedInt dim,CeedInt p_to_dim,CeedInt p_from_dim,CeedVector x_to,CeedVector x_from,CeedVector u_to,CeedVector u_from,CeedVector du_to)38097cc795SJames Wright static void VerifyProjectedBasis(CeedBasis basis_project, CeedInt dim, CeedInt p_to_dim, CeedInt p_from_dim, CeedVector x_to, CeedVector x_from,
39097cc795SJames Wright CeedVector u_to, CeedVector u_from, CeedVector du_to) {
4099e754f0SJeremy L Thompson CeedScalar tol;
414fee36f0SJeremy L Thompson
4299e754f0SJeremy L Thompson {
4399e754f0SJeremy L Thompson CeedScalarType scalar_type;
4499e754f0SJeremy L Thompson
4599e754f0SJeremy L Thompson CeedGetScalarType(&scalar_type);
4699e754f0SJeremy L Thompson tol = GetTolerance(scalar_type, dim);
4799e754f0SJeremy L Thompson }
4814556e63SJeremy L Thompson
4914556e63SJeremy L Thompson // Setup coarse solution
504fee36f0SJeremy L Thompson {
514fee36f0SJeremy L Thompson const CeedScalar *x_array;
524fee36f0SJeremy L Thompson CeedScalar u_array[p_from_dim];
534fee36f0SJeremy L Thompson
544fee36f0SJeremy L Thompson CeedVectorGetArrayRead(x_from, CEED_MEM_HOST, &x_array);
554fee36f0SJeremy L Thompson for (CeedInt i = 0; i < p_from_dim; i++) {
564fee36f0SJeremy L Thompson CeedScalar coord[dim];
574fee36f0SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[p_from_dim * d + i];
584fee36f0SJeremy L Thompson u_array[i] = Eval(dim, coord);
5914556e63SJeremy L Thompson }
604fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(x_from, &x_array);
614fee36f0SJeremy L Thompson CeedVectorSetArray(u_from, CEED_MEM_HOST, CEED_COPY_VALUES, u_array);
624fee36f0SJeremy L Thompson }
6314556e63SJeremy L Thompson
6414556e63SJeremy L Thompson // Project to fine basis
654fee36f0SJeremy L Thompson CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, u_from, u_to);
6614556e63SJeremy L Thompson
6714556e63SJeremy L Thompson // Check solution
684fee36f0SJeremy L Thompson {
694fee36f0SJeremy L Thompson const CeedScalar *x_array, *u_array;
704fee36f0SJeremy L Thompson
714fee36f0SJeremy L Thompson CeedVectorGetArrayRead(x_to, CEED_MEM_HOST, &x_array);
724fee36f0SJeremy L Thompson CeedVectorGetArrayRead(u_to, CEED_MEM_HOST, &u_array);
734fee36f0SJeremy L Thompson for (CeedInt i = 0; i < p_to_dim; i++) {
744fee36f0SJeremy L Thompson CeedScalar coord[dim];
754fee36f0SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[d * p_to_dim + i];
764fee36f0SJeremy L Thompson const CeedScalar u = Eval(dim, coord);
774fee36f0SJeremy L Thompson if (fabs(u - u_array[i]) > tol) printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, u_array[i], u);
7814556e63SJeremy L Thompson }
794fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(x_to, &x_array);
804fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(u_to, &u_array);
814fee36f0SJeremy L Thompson }
8214556e63SJeremy L Thompson
8314556e63SJeremy L Thompson // Project and take gradient
844fee36f0SJeremy L Thompson CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, u_from, du_to);
8514556e63SJeremy L Thompson
8614556e63SJeremy L Thompson // Check solution
874fee36f0SJeremy L Thompson {
884fee36f0SJeremy L Thompson const CeedScalar *x_array, *du_array;
894fee36f0SJeremy L Thompson
904fee36f0SJeremy L Thompson CeedVectorGetArrayRead(x_to, CEED_MEM_HOST, &x_array);
914fee36f0SJeremy L Thompson CeedVectorGetArrayRead(du_to, CEED_MEM_HOST, &du_array);
924fee36f0SJeremy L Thompson for (CeedInt i = 0; i < p_to_dim; i++) {
934fee36f0SJeremy L Thompson CeedScalar coord[dim];
9499e754f0SJeremy L Thompson
954fee36f0SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[p_to_dim * d + i];
9614556e63SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) {
974fee36f0SJeremy L Thompson const CeedScalar du = EvalGrad(d, coord);
9899e754f0SJeremy L Thompson
993c9d155aSZach Atkins if (fabs(du - du_array[p_to_dim * d + i]) > tol) {
10014556e63SJeremy L Thompson // LCOV_EXCL_START
1014fee36f0SJeremy 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);
10214556e63SJeremy L Thompson // LCOV_EXCL_STOP
10314556e63SJeremy L Thompson }
10414556e63SJeremy L Thompson }
1052b730f8bSJeremy L Thompson }
1064fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(x_to, &x_array);
1074fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(du_to, &du_array);
1084fee36f0SJeremy L Thompson }
109097cc795SJames Wright }
110097cc795SJames Wright
main(int argc,char ** argv)111097cc795SJames Wright int main(int argc, char **argv) {
112097cc795SJames Wright Ceed ceed;
113097cc795SJames Wright
114097cc795SJames Wright CeedInit(argv[1], &ceed);
115097cc795SJames Wright
116097cc795SJames Wright for (CeedInt dim = 1; dim <= 3; dim++) {
117097cc795SJames Wright CeedVector x_corners, x_from, x_to, u_from, u_to, du_to;
118097cc795SJames Wright CeedBasis basis_x, basis_from, basis_to, basis_project;
119*fda26546SJeremy L Thompson CeedInt p_from = 4, p_to = 5, q = 6, x_dim = CeedIntPow(2, dim), p_from_dim = CeedIntPow(p_from, dim), p_to_dim = CeedIntPow(p_to, dim);
120097cc795SJames Wright
121097cc795SJames Wright CeedVectorCreate(ceed, x_dim * dim, &x_corners);
122097cc795SJames Wright {
123097cc795SJames Wright CeedScalar x_array[x_dim * dim];
124097cc795SJames Wright
125097cc795SJames Wright for (CeedInt d = 0; d < dim; d++) {
126097cc795SJames 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;
127097cc795SJames Wright }
128097cc795SJames Wright CeedVectorSetArray(x_corners, CEED_MEM_HOST, CEED_COPY_VALUES, x_array);
129097cc795SJames Wright }
130097cc795SJames Wright CeedVectorCreate(ceed, p_from_dim * dim, &x_from);
131097cc795SJames Wright CeedVectorCreate(ceed, p_to_dim * dim, &x_to);
132097cc795SJames Wright CeedVectorCreate(ceed, p_from_dim, &u_from);
133097cc795SJames Wright CeedVectorSetValue(u_from, 0);
134097cc795SJames Wright CeedVectorCreate(ceed, p_to_dim, &u_to);
135097cc795SJames Wright CeedVectorSetValue(u_to, 0);
136097cc795SJames Wright CeedVectorCreate(ceed, p_to_dim * dim, &du_to);
137097cc795SJames Wright CeedVectorSetValue(du_to, 0);
138097cc795SJames Wright
139097cc795SJames Wright // Get nodal coordinates
140097cc795SJames Wright CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, p_from, CEED_GAUSS_LOBATTO, &basis_x);
141097cc795SJames Wright CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, x_corners, x_from);
142097cc795SJames Wright CeedBasisDestroy(&basis_x);
143097cc795SJames Wright CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, p_to, CEED_GAUSS_LOBATTO, &basis_x);
144097cc795SJames Wright CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, x_corners, x_to);
145097cc795SJames Wright CeedBasisDestroy(&basis_x);
146097cc795SJames Wright
147097cc795SJames Wright // Create U and projection bases
148097cc795SJames Wright CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p_from, q, CEED_GAUSS, &basis_from);
149097cc795SJames Wright CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p_to, q, CEED_GAUSS, &basis_to);
150097cc795SJames Wright CeedBasisCreateProjection(basis_from, basis_to, &basis_project);
151097cc795SJames Wright
152097cc795SJames Wright VerifyProjectedBasis(basis_project, dim, p_to_dim, p_from_dim, x_to, x_from, u_to, u_from, du_to);
153097cc795SJames Wright
154e104ad11SJames Wright // Create non-tensor bases
155097cc795SJames Wright CeedBasis basis_from_nontensor, basis_to_nontensor;
156e104ad11SJames Wright {
157097cc795SJames Wright CeedElemTopology topo;
158cb270d31SJeremy L Thompson CeedInt num_comp, num_nodes, num_qpts;
159097cc795SJames Wright const CeedScalar *interp, *grad;
160097cc795SJames Wright
161097cc795SJames Wright CeedBasisGetTopology(basis_from, &topo);
162097cc795SJames Wright CeedBasisGetNumComponents(basis_from, &num_comp);
163097cc795SJames Wright CeedBasisGetNumNodes(basis_from, &num_nodes);
164cb270d31SJeremy L Thompson CeedBasisGetNumQuadraturePoints(basis_from, &num_qpts);
165097cc795SJames Wright CeedBasisGetInterp(basis_from, &interp);
166097cc795SJames Wright CeedBasisGetGrad(basis_from, &grad);
167cb270d31SJeremy L Thompson CeedBasisCreateH1(ceed, topo, num_comp, num_nodes, num_qpts, interp, grad, NULL, NULL, &basis_from_nontensor);
168097cc795SJames Wright
169097cc795SJames Wright CeedBasisGetTopology(basis_to, &topo);
170097cc795SJames Wright CeedBasisGetNumComponents(basis_to, &num_comp);
171097cc795SJames Wright CeedBasisGetNumNodes(basis_to, &num_nodes);
172cb270d31SJeremy L Thompson CeedBasisGetNumQuadraturePoints(basis_to, &num_qpts);
173097cc795SJames Wright CeedBasisGetInterp(basis_to, &interp);
174097cc795SJames Wright CeedBasisGetGrad(basis_to, &grad);
175cb270d31SJeremy L Thompson CeedBasisCreateH1(ceed, topo, num_comp, num_nodes, num_qpts, interp, grad, NULL, NULL, &basis_to_nontensor);
176097cc795SJames Wright }
177097cc795SJames Wright
178e104ad11SJames Wright // Test projection on non-tensor bases
179e104ad11SJames Wright CeedBasisDestroy(&basis_project);
180e104ad11SJames Wright CeedBasisCreateProjection(basis_from_nontensor, basis_to_nontensor, &basis_project);
181e104ad11SJames Wright VerifyProjectedBasis(basis_project, dim, p_to_dim, p_from_dim, x_to, x_from, u_to, u_from, du_to);
182e104ad11SJames Wright
183e104ad11SJames Wright // Test projection from non-tensor to tensor
184e104ad11SJames Wright CeedBasisDestroy(&basis_project);
185e104ad11SJames Wright CeedBasisCreateProjection(basis_from_nontensor, basis_to, &basis_project);
186e104ad11SJames Wright VerifyProjectedBasis(basis_project, dim, p_to_dim, p_from_dim, x_to, x_from, u_to, u_from, du_to);
187e104ad11SJames Wright
188e104ad11SJames Wright // Test projection from tensor to non-tensor
189e104ad11SJames Wright CeedBasisDestroy(&basis_project);
190e104ad11SJames Wright CeedBasisCreateProjection(basis_from, basis_to_nontensor, &basis_project);
191097cc795SJames Wright VerifyProjectedBasis(basis_project, dim, p_to_dim, p_from_dim, x_to, x_from, u_to, u_from, du_to);
19214556e63SJeremy L Thompson
1934fee36f0SJeremy L Thompson CeedVectorDestroy(&x_corners);
1944fee36f0SJeremy L Thompson CeedVectorDestroy(&x_from);
1954fee36f0SJeremy L Thompson CeedVectorDestroy(&x_to);
1964fee36f0SJeremy L Thompson CeedVectorDestroy(&u_from);
1974fee36f0SJeremy L Thompson CeedVectorDestroy(&u_to);
1984fee36f0SJeremy L Thompson CeedVectorDestroy(&du_to);
19914556e63SJeremy L Thompson CeedBasisDestroy(&basis_from);
200e104ad11SJames Wright CeedBasisDestroy(&basis_from_nontensor);
20114556e63SJeremy L Thompson CeedBasisDestroy(&basis_to);
202e104ad11SJames Wright CeedBasisDestroy(&basis_to_nontensor);
20314556e63SJeremy L Thompson CeedBasisDestroy(&basis_project);
20414556e63SJeremy L Thompson }
205706bf528SJames Wright
206706bf528SJames Wright // Test projection between basis of different topological dimension
207706bf528SJames Wright {
208706bf528SJames Wright CeedInt face_dim = 2, P_1D = 2;
209706bf528SJames Wright CeedBasis basis_face, basis_cell_to_face, basis_proj;
210706bf528SJames Wright
211706bf528SJames Wright CeedScalar *q_ref = NULL, *q_weights = NULL;
212706bf528SJames Wright const CeedScalar *grad, *interp;
213706bf528SJames Wright CeedInt P, Q;
214706bf528SJames Wright GetCellToFaceTabulation(CEED_GAUSS, &P, &Q, &interp, &grad);
215706bf528SJames Wright
216706bf528SJames Wright CeedBasisCreateTensorH1Lagrange(ceed, face_dim, 1, 2, P_1D, CEED_GAUSS, &basis_face);
217706bf528SJames Wright CeedBasisCreateH1(ceed, CEED_TOPOLOGY_HEX, 1, P, Q, (CeedScalar *)interp, (CeedScalar *)grad, q_ref, q_weights, &basis_cell_to_face);
218706bf528SJames Wright CeedBasisCreateProjection(basis_cell_to_face, basis_face, &basis_proj);
219706bf528SJames Wright const CeedScalar *interp_proj, *grad_proj, *interp_proj_ref, *grad_proj_ref;
220706bf528SJames Wright
221706bf528SJames Wright GetCellToFaceTabulation(CEED_GAUSS_LOBATTO, NULL, NULL, &interp_proj_ref, &grad_proj_ref);
222706bf528SJames Wright CeedBasisGetInterp(basis_proj, &interp_proj);
223706bf528SJames Wright CeedBasisGetGrad(basis_proj, &grad_proj);
224706bf528SJames Wright CeedScalar tol = 100 * CEED_EPSILON;
225706bf528SJames Wright
226706bf528SJames Wright for (CeedInt i = 0; i < 4 * 8; i++) {
2276c10af5dSJeremy L Thompson if (fabs(interp_proj[i] - ((CeedScalar *)interp_proj_ref)[i]) > tol) {
2286c10af5dSJeremy L Thompson // LCOV_EXCL_START
229706bf528SJames Wright printf("Mixed Topology Projection: interp[%" CeedInt_FMT "] expected %f, got %f\n", i, interp_proj[i], ((CeedScalar *)interp_proj_ref)[i]);
2306c10af5dSJeremy L Thompson // LCOV_EXCL_STOP
2316c10af5dSJeremy L Thompson }
232706bf528SJames Wright }
233706bf528SJames Wright
234706bf528SJames Wright for (CeedInt i = 0; i < 3 * 4 * 8; i++) {
2356c10af5dSJeremy L Thompson if (fabs(grad_proj[i] - ((CeedScalar *)grad_proj_ref)[i]) > tol) {
2366c10af5dSJeremy L Thompson // LCOV_EXCL_START
237706bf528SJames Wright printf("Mixed Topology Projection: grad[%" CeedInt_FMT "] expected %f, got %f\n", i, grad_proj[i], ((CeedScalar *)grad_proj_ref)[i]);
2386c10af5dSJeremy L Thompson // LCOV_EXCL_STOP
2396c10af5dSJeremy L Thompson }
240706bf528SJames Wright }
241706bf528SJames Wright
242706bf528SJames Wright CeedBasisDestroy(&basis_face);
243706bf528SJames Wright CeedBasisDestroy(&basis_cell_to_face);
244706bf528SJames Wright CeedBasisDestroy(&basis_proj);
245706bf528SJames Wright }
24614556e63SJeremy L Thompson CeedDestroy(&ceed);
24714556e63SJeremy L Thompson return 0;
24814556e63SJeremy L Thompson }
249