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