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