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) { 162b730f8bSJeremy L Thompson case 0: 172b730f8bSJeremy L Thompson return 2 * x[0] + 0.2; 182b730f8bSJeremy L Thompson case 1: 192b730f8bSJeremy L Thompson return 2 * x[1] + 0.4; 202b730f8bSJeremy L Thompson default: 212b730f8bSJeremy 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) { 282b730f8bSJeremy L Thompson if (dim == 3) tol = 1.e-4; 292b730f8bSJeremy 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++) { 42*4fee36f0SJeremy 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*4fee36f0SJeremy 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); 45*4fee36f0SJeremy L Thompson 46*4fee36f0SJeremy L Thompson CeedVectorCreate(ceed, x_dim * dim, &x_corners); 47*4fee36f0SJeremy L Thompson { 48*4fee36f0SJeremy L Thompson CeedScalar x_array[x_dim * dim]; 4914556e63SJeremy L Thompson 502b730f8bSJeremy L Thompson for (CeedInt d = 0; d < dim; d++) { 51*4fee36f0SJeremy L Thompson for (CeedInt i = 0; i < x_dim; i++) x_array[x_dim * d + i] = (i % CeedIntPow(2, dim - d)) / CeedIntPow(2, dim - d - 1) ? 1 : -1; 522b730f8bSJeremy L Thompson } 53*4fee36f0SJeremy L Thompson CeedVectorSetArray(x_corners, CEED_MEM_HOST, CEED_COPY_VALUES, x_array); 54*4fee36f0SJeremy L Thompson } 55*4fee36f0SJeremy L Thompson CeedVectorCreate(ceed, p_from_dim * dim, &x_from); 56*4fee36f0SJeremy L Thompson CeedVectorCreate(ceed, p_to_dim * dim, &x_to); 57*4fee36f0SJeremy L Thompson CeedVectorCreate(ceed, p_from_dim, &u_from); 58*4fee36f0SJeremy L Thompson CeedVectorSetValue(u_from, 0); 59*4fee36f0SJeremy L Thompson CeedVectorCreate(ceed, p_to_dim, &u_to); 60*4fee36f0SJeremy L Thompson CeedVectorSetValue(u_to, 0); 61*4fee36f0SJeremy L Thompson CeedVectorCreate(ceed, p_to_dim * dim, &du_to); 62*4fee36f0SJeremy L Thompson CeedVectorSetValue(du_to, 0); 6314556e63SJeremy L Thompson 6414556e63SJeremy L Thompson // Get nodal coordinates 65*4fee36f0SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, p_from, CEED_GAUSS_LOBATTO, &basis_x); 66*4fee36f0SJeremy L Thompson CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, x_corners, x_from); 6714556e63SJeremy L Thompson CeedBasisDestroy(&basis_x); 68*4fee36f0SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, p_to, CEED_GAUSS_LOBATTO, &basis_x); 69*4fee36f0SJeremy L Thompson CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, x_corners, x_to); 7014556e63SJeremy L Thompson CeedBasisDestroy(&basis_x); 7114556e63SJeremy L Thompson 7214556e63SJeremy L Thompson // Create U and projection bases 73*4fee36f0SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p_from, q, CEED_GAUSS, &basis_from); 74*4fee36f0SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p_to, q, CEED_GAUSS, &basis_to); 7514556e63SJeremy L Thompson CeedBasisCreateProjection(basis_from, basis_to, &basis_project); 7614556e63SJeremy L Thompson 7714556e63SJeremy L Thompson // Setup coarse solution 78*4fee36f0SJeremy L Thompson { 79*4fee36f0SJeremy L Thompson const CeedScalar *x_array; 80*4fee36f0SJeremy L Thompson CeedScalar u_array[p_from_dim]; 81*4fee36f0SJeremy L Thompson 82*4fee36f0SJeremy L Thompson CeedVectorGetArrayRead(x_from, CEED_MEM_HOST, &x_array); 83*4fee36f0SJeremy L Thompson for (CeedInt i = 0; i < p_from_dim; i++) { 84*4fee36f0SJeremy L Thompson CeedScalar coord[dim]; 85*4fee36f0SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[p_from_dim * d + i]; 86*4fee36f0SJeremy L Thompson u_array[i] = Eval(dim, coord); 8714556e63SJeremy L Thompson } 88*4fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(x_from, &x_array); 89*4fee36f0SJeremy L Thompson CeedVectorSetArray(u_from, CEED_MEM_HOST, CEED_COPY_VALUES, u_array); 90*4fee36f0SJeremy L Thompson } 9114556e63SJeremy L Thompson 9214556e63SJeremy L Thompson // Project to fine basis 93*4fee36f0SJeremy L Thompson CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, u_from, u_to); 9414556e63SJeremy L Thompson 9514556e63SJeremy L Thompson // Check solution 9614556e63SJeremy L Thompson CeedScalar tol = GetTolerance(CEED_SCALAR_TYPE, dim); 97*4fee36f0SJeremy L Thompson { 98*4fee36f0SJeremy L Thompson const CeedScalar *x_array, *u_array; 99*4fee36f0SJeremy L Thompson 100*4fee36f0SJeremy L Thompson CeedVectorGetArrayRead(x_to, CEED_MEM_HOST, &x_array); 101*4fee36f0SJeremy L Thompson CeedVectorGetArrayRead(u_to, CEED_MEM_HOST, &u_array); 102*4fee36f0SJeremy L Thompson for (CeedInt i = 0; i < p_to_dim; i++) { 103*4fee36f0SJeremy L Thompson CeedScalar coord[dim]; 104*4fee36f0SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[d * p_to_dim + i]; 105*4fee36f0SJeremy L Thompson const CeedScalar u = Eval(dim, coord); 106*4fee36f0SJeremy L Thompson if (fabs(u - u_array[i]) > tol) printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, u_array[i], u); 10714556e63SJeremy L Thompson } 108*4fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(x_to, &x_array); 109*4fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(u_to, &u_array); 110*4fee36f0SJeremy L Thompson } 11114556e63SJeremy L Thompson 11214556e63SJeremy L Thompson // Project and take gradient 113*4fee36f0SJeremy L Thompson CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, u_from, du_to); 11414556e63SJeremy L Thompson 11514556e63SJeremy L Thompson // Check solution 116*4fee36f0SJeremy L Thompson { 117*4fee36f0SJeremy L Thompson const CeedScalar *x_array, *du_array; 118*4fee36f0SJeremy L Thompson 119*4fee36f0SJeremy L Thompson CeedVectorGetArrayRead(x_to, CEED_MEM_HOST, &x_array); 120*4fee36f0SJeremy L Thompson CeedVectorGetArrayRead(du_to, CEED_MEM_HOST, &du_array); 121*4fee36f0SJeremy L Thompson for (CeedInt i = 0; i < p_to_dim; i++) { 122*4fee36f0SJeremy L Thompson CeedScalar coord[dim]; 123*4fee36f0SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[p_to_dim * d + i]; 12414556e63SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) { 125*4fee36f0SJeremy L Thompson const CeedScalar du = EvalGrad(d, coord); 126*4fee36f0SJeremy L Thompson if (fabs(du - du_array[p_to_dim * (dim - 1 - d) + i]) > tol) { 12714556e63SJeremy L Thompson // LCOV_EXCL_START 128*4fee36f0SJeremy 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); 12914556e63SJeremy L Thompson // LCOV_EXCL_STOP 13014556e63SJeremy L Thompson } 13114556e63SJeremy L Thompson } 1322b730f8bSJeremy L Thompson } 133*4fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(x_to, &x_array); 134*4fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(du_to, &du_array); 135*4fee36f0SJeremy L Thompson } 13614556e63SJeremy L Thompson 137*4fee36f0SJeremy L Thompson CeedVectorDestroy(&x_corners); 138*4fee36f0SJeremy L Thompson CeedVectorDestroy(&x_from); 139*4fee36f0SJeremy L Thompson CeedVectorDestroy(&x_to); 140*4fee36f0SJeremy L Thompson CeedVectorDestroy(&u_from); 141*4fee36f0SJeremy L Thompson CeedVectorDestroy(&u_to); 142*4fee36f0SJeremy L Thompson CeedVectorDestroy(&du_to); 14314556e63SJeremy L Thompson CeedBasisDestroy(&basis_from); 14414556e63SJeremy L Thompson CeedBasisDestroy(&basis_to); 14514556e63SJeremy L Thompson CeedBasisDestroy(&basis_project); 14614556e63SJeremy L Thompson } 14714556e63SJeremy L Thompson CeedDestroy(&ceed); 14814556e63SJeremy L Thompson return 0; 14914556e63SJeremy L Thompson } 150