1*14556e63SJeremy L Thompson /// @file 2*14556e63SJeremy L Thompson /// Test projection interp and grad in multiple dimensions 3*14556e63SJeremy L Thompson /// \test Test projection interp and grad in multiple dimensions 4*14556e63SJeremy L Thompson #include <ceed.h> 5*14556e63SJeremy L Thompson #include <math.h> 6*14556e63SJeremy L Thompson 7*14556e63SJeremy L Thompson static CeedScalar Eval(CeedInt dim, const CeedScalar x[]) { 8*14556e63SJeremy L Thompson CeedScalar result = (x[0] + 0.1) * (x[0] + 0.1); 9*14556e63SJeremy L Thompson if (dim > 1) result += (x[1] + 0.2) * (x[1] + 0.2); 10*14556e63SJeremy L Thompson if (dim > 2) result += -(x[2] + 0.3) * (x[2] + 0.3); 11*14556e63SJeremy L Thompson return result; 12*14556e63SJeremy L Thompson } 13*14556e63SJeremy L Thompson 14*14556e63SJeremy L Thompson static CeedScalar EvalGrad(CeedInt dim, const CeedScalar x[]) { 15*14556e63SJeremy L Thompson switch (dim) { 16*14556e63SJeremy L Thompson case 0: return 2 * x[0] + 0.2; 17*14556e63SJeremy L Thompson case 1: return 2 * x[1] + 0.4; 18*14556e63SJeremy L Thompson default: return -2 * x[2] - 0.6; 19*14556e63SJeremy L Thompson } 20*14556e63SJeremy L Thompson } 21*14556e63SJeremy L Thompson 22*14556e63SJeremy L Thompson static CeedScalar GetTolerance(CeedScalarType scalar_type, int dim) { 23*14556e63SJeremy L Thompson CeedScalar tol; 24*14556e63SJeremy L Thompson if (scalar_type == CEED_SCALAR_FP32) { 25*14556e63SJeremy L Thompson if (dim == 3) 26*14556e63SJeremy L Thompson tol = 1.e-4; 27*14556e63SJeremy L Thompson else 28*14556e63SJeremy L Thompson tol = 1.e-5; 29*14556e63SJeremy L Thompson } else { 30*14556e63SJeremy L Thompson tol = 1.e-11; 31*14556e63SJeremy L Thompson } 32*14556e63SJeremy L Thompson return tol; 33*14556e63SJeremy L Thompson } 34*14556e63SJeremy L Thompson 35*14556e63SJeremy L Thompson int main(int argc, char **argv) { 36*14556e63SJeremy L Thompson Ceed ceed; 37*14556e63SJeremy L Thompson 38*14556e63SJeremy L Thompson CeedInit(argv[1], &ceed); 39*14556e63SJeremy L Thompson 40*14556e63SJeremy L Thompson for (CeedInt dim = 1; dim <= 3; dim++) { 41*14556e63SJeremy L Thompson CeedVector X_corners, X_from, X_to, U_from, U_to, dU_to; 42*14556e63SJeremy L Thompson CeedBasis basis_x, basis_from, basis_to, basis_project; 43*14556e63SJeremy L Thompson CeedInt P_from = 5, P_to = 6, Q = 7, X_dim = CeedIntPow(2, dim), 44*14556e63SJeremy L Thompson P_from_dim = CeedIntPow(P_from, dim), P_to_dim = CeedIntPow(P_to, dim); 45*14556e63SJeremy L Thompson CeedScalar x[X_dim * dim], u_from[P_from_dim]; 46*14556e63SJeremy L Thompson const CeedScalar *u_to, *du_to, *x_from, *x_to; 47*14556e63SJeremy L Thompson 48*14556e63SJeremy L Thompson for (CeedInt d=0; d<dim; d++) 49*14556e63SJeremy L Thompson for (CeedInt i=0; i<X_dim; i++) 50*14556e63SJeremy L Thompson x[X_dim * d + i] = (i % CeedIntPow(2, dim-d)) / 51*14556e63SJeremy L Thompson CeedIntPow(2, dim-d-1) ? 1 : -1; 52*14556e63SJeremy L Thompson 53*14556e63SJeremy L Thompson CeedVectorCreate(ceed, X_dim * dim, &X_corners); 54*14556e63SJeremy L Thompson CeedVectorSetArray(X_corners, CEED_MEM_HOST, CEED_USE_POINTER, x); 55*14556e63SJeremy L Thompson CeedVectorCreate(ceed, P_from_dim * dim, &X_from); 56*14556e63SJeremy L Thompson CeedVectorCreate(ceed, P_to_dim * dim, &X_to); 57*14556e63SJeremy L Thompson CeedVectorCreate(ceed, P_from_dim, &U_from); 58*14556e63SJeremy L Thompson CeedVectorSetValue(U_from, 0); 59*14556e63SJeremy L Thompson CeedVectorCreate(ceed, P_to_dim, &U_to); 60*14556e63SJeremy L Thompson CeedVectorSetValue(U_to, 0); 61*14556e63SJeremy L Thompson CeedVectorCreate(ceed, P_to_dim * dim, &dU_to); 62*14556e63SJeremy L Thompson CeedVectorSetValue(dU_to, 0); 63*14556e63SJeremy L Thompson 64*14556e63SJeremy L Thompson // Get nodal coordinates 65*14556e63SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, P_from, 66*14556e63SJeremy L Thompson CEED_GAUSS_LOBATTO, &basis_x); 67*14556e63SJeremy L Thompson CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, X_corners, 68*14556e63SJeremy L Thompson X_from); 69*14556e63SJeremy L Thompson CeedBasisDestroy(&basis_x); 70*14556e63SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, P_to, 71*14556e63SJeremy L Thompson CEED_GAUSS_LOBATTO, &basis_x); 72*14556e63SJeremy L Thompson CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, X_corners, X_to); 73*14556e63SJeremy L Thompson CeedBasisDestroy(&basis_x); 74*14556e63SJeremy L Thompson 75*14556e63SJeremy L Thompson // Create U and projection bases 76*14556e63SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P_from, Q, CEED_GAUSS, 77*14556e63SJeremy L Thompson &basis_from); 78*14556e63SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P_to, Q, CEED_GAUSS, &basis_to); 79*14556e63SJeremy L Thompson CeedBasisCreateProjection(basis_from, basis_to, &basis_project); 80*14556e63SJeremy L Thompson 81*14556e63SJeremy L Thompson // Setup coarse solution 82*14556e63SJeremy L Thompson CeedVectorGetArrayRead(X_from, CEED_MEM_HOST, &x_from); 83*14556e63SJeremy L Thompson for (CeedInt i=0; i<P_from_dim; i++) { 84*14556e63SJeremy L Thompson CeedScalar xx[dim]; 85*14556e63SJeremy L Thompson for (CeedInt d=0; d<dim; d++) xx[d] = x_from[P_from_dim * d + i]; 86*14556e63SJeremy L Thompson u_from[i] = Eval(dim, xx); 87*14556e63SJeremy L Thompson } 88*14556e63SJeremy L Thompson CeedVectorRestoreArrayRead(X_from, &x_from); 89*14556e63SJeremy L Thompson CeedVectorSetArray(U_from, CEED_MEM_HOST, CEED_USE_POINTER, u_from); 90*14556e63SJeremy L Thompson 91*14556e63SJeremy L Thompson // Project to fine basis 92*14556e63SJeremy L Thompson CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, U_from, 93*14556e63SJeremy L Thompson U_to); 94*14556e63SJeremy L Thompson 95*14556e63SJeremy L Thompson // Check solution 96*14556e63SJeremy L Thompson CeedVectorGetArrayRead(U_to, CEED_MEM_HOST, &u_to); 97*14556e63SJeremy L Thompson CeedVectorGetArrayRead(X_to, CEED_MEM_HOST, &x_to); 98*14556e63SJeremy L Thompson CeedScalar tol = GetTolerance(CEED_SCALAR_TYPE, dim); 99*14556e63SJeremy L Thompson for (CeedInt i=0; i<P_to_dim; i++) { 100*14556e63SJeremy L Thompson CeedScalar xx[dim]; 101*14556e63SJeremy L Thompson for (CeedInt d=0; d<dim; d++) xx[d] = x_to[d*P_to_dim + i]; 102*14556e63SJeremy L Thompson const CeedScalar u = Eval(dim, xx); 103*14556e63SJeremy L Thompson if (fabs(u - u_to[i]) > tol) 104*14556e63SJeremy L Thompson // LCOV_EXCL_START 105*14556e63SJeremy L Thompson printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, i, u_to[i], u); 106*14556e63SJeremy L Thompson // LCOV_EXCL_STOP 107*14556e63SJeremy L Thompson } 108*14556e63SJeremy L Thompson CeedVectorRestoreArrayRead(X_to, &x_to); 109*14556e63SJeremy L Thompson CeedVectorRestoreArrayRead(U_to, &u_to); 110*14556e63SJeremy L Thompson 111*14556e63SJeremy L Thompson // Project and take gradient 112*14556e63SJeremy L Thompson CeedBasisApply(basis_project, 1, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, U_from, 113*14556e63SJeremy L Thompson dU_to); 114*14556e63SJeremy L Thompson 115*14556e63SJeremy L Thompson // Check solution 116*14556e63SJeremy L Thompson CeedVectorGetArrayRead(dU_to, CEED_MEM_HOST, &du_to); 117*14556e63SJeremy L Thompson CeedVectorGetArrayRead(X_to, CEED_MEM_HOST, &x_to); 118*14556e63SJeremy L Thompson for (CeedInt i=0; i<P_to_dim; i++) { 119*14556e63SJeremy L Thompson CeedScalar xx[dim]; 120*14556e63SJeremy L Thompson for (CeedInt d=0; d<dim; d++) xx[d] = x_to[P_to_dim * d + i]; 121*14556e63SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 122*14556e63SJeremy L Thompson const CeedScalar du = EvalGrad(d, xx); 123*14556e63SJeremy L Thompson if (fabs(du - du_to[P_to_dim * (dim - 1 - d) + i]) > tol) 124*14556e63SJeremy L Thompson // LCOV_EXCL_START 125*14556e63SJeremy L Thompson printf("[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "] %f != %f\n", dim, 126*14556e63SJeremy L Thompson i, d, du_to[P_to_dim * (dim - 1 - d) + i], du); 127*14556e63SJeremy L Thompson // LCOV_EXCL_STOP 128*14556e63SJeremy L Thompson } 129*14556e63SJeremy L Thompson } 130*14556e63SJeremy L Thompson CeedVectorRestoreArrayRead(X_to, &x_to); 131*14556e63SJeremy L Thompson CeedVectorRestoreArrayRead(dU_to, &du_to); 132*14556e63SJeremy L Thompson 133*14556e63SJeremy L Thompson CeedVectorDestroy(&X_corners); 134*14556e63SJeremy L Thompson CeedVectorDestroy(&X_from); 135*14556e63SJeremy L Thompson CeedVectorDestroy(&X_to); 136*14556e63SJeremy L Thompson CeedVectorDestroy(&U_from); 137*14556e63SJeremy L Thompson CeedVectorDestroy(&U_to); 138*14556e63SJeremy L Thompson CeedVectorDestroy(&dU_to); 139*14556e63SJeremy L Thompson CeedBasisDestroy(&basis_from); 140*14556e63SJeremy L Thompson CeedBasisDestroy(&basis_to); 141*14556e63SJeremy L Thompson CeedBasisDestroy(&basis_project); 142*14556e63SJeremy L Thompson } 143*14556e63SJeremy L Thompson CeedDestroy(&ceed); 144*14556e63SJeremy L Thompson return 0; 145*14556e63SJeremy L Thompson } 146