13bd813ffSjeremylt /// @file 23bd813ffSjeremylt /// Test creation and use of FDM element inverse 33bd813ffSjeremylt /// \test Test creation and use of FDM element inverse 43bd813ffSjeremylt #include <ceed.h> 53bd813ffSjeremylt #include <stdlib.h> 63bd813ffSjeremylt #include <math.h> 73bd813ffSjeremylt #include "t540-operator.h" 83bd813ffSjeremylt 93bd813ffSjeremylt int main(int argc, char **argv) { 103bd813ffSjeremylt Ceed ceed; 11*d1d35e2fSjeremylt CeedElemRestriction elem_restr_x_i, elem_restr_u_i, elem_restr_qd_i; 12*d1d35e2fSjeremylt CeedBasis basis_x, basis_u; 133bd813ffSjeremylt CeedQFunction qf_setup_mass, qf_apply; 143bd813ffSjeremylt CeedOperator op_setup_mass, op_apply, op_inv; 15*d1d35e2fSjeremylt CeedVector q_data_mass, X, U, V; 16*d1d35e2fSjeremylt CeedInt num_elem = 1, P = 4, Q = 5, dim = 2; 17*d1d35e2fSjeremylt CeedInt num_dofs = P*P, num_qpts = num_elem*Q*Q; 18*d1d35e2fSjeremylt CeedScalar x[dim*num_elem*(2*2)]; 193bd813ffSjeremylt const CeedScalar *u; 203bd813ffSjeremylt 213bd813ffSjeremylt CeedInit(argv[1], &ceed); 223bd813ffSjeremylt 233bd813ffSjeremylt // DoF Coordinates 243bd813ffSjeremylt for (CeedInt i=0; i<2; i++) 253bd813ffSjeremylt for (CeedInt j=0; j<2; j++) { 263bd813ffSjeremylt x[i+j*2+0*4] = i; 273bd813ffSjeremylt x[i+j*2+1*4] = j; 283bd813ffSjeremylt } 29*d1d35e2fSjeremylt CeedVectorCreate(ceed, dim*num_elem*(2*2), &X); 303bd813ffSjeremylt CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x); 313bd813ffSjeremylt 323bd813ffSjeremylt // Qdata Vector 33*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts, &q_data_mass); 343bd813ffSjeremylt 353bd813ffSjeremylt // Element Setup 363bd813ffSjeremylt 373bd813ffSjeremylt // Restrictions 38*d1d35e2fSjeremylt CeedInt strides_x[3] = {1, 2*2, 2*2*dim}; 39*d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, 2*2, dim, dim*num_elem*2*2, 40*d1d35e2fSjeremylt strides_x, &elem_restr_x_i); 413bd813ffSjeremylt 42*d1d35e2fSjeremylt CeedInt strides_u[3] = {1, P*P, P*P}; 43*d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, P*P, 1, num_dofs, strides_u, 44*d1d35e2fSjeremylt &elem_restr_u_i); 453bd813ffSjeremylt 46*d1d35e2fSjeremylt CeedInt strides_qd[3] = {1, Q*Q, Q*Q}; 47*d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, Q*Q, 1, num_qpts, strides_qd, 48*d1d35e2fSjeremylt &elem_restr_qd_i); 493bd813ffSjeremylt 503bd813ffSjeremylt // Bases 51*d1d35e2fSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, Q, CEED_GAUSS, &basis_x); 52*d1d35e2fSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P, Q, CEED_GAUSS, &basis_u); 533bd813ffSjeremylt 543bd813ffSjeremylt // QFunction - setup mass 553bd813ffSjeremylt CeedQFunctionCreateInterior(ceed, 1, setup_mass, setup_mass_loc, 563bd813ffSjeremylt &qf_setup_mass); 573bd813ffSjeremylt CeedQFunctionAddInput(qf_setup_mass, "dx", dim*dim, CEED_EVAL_GRAD); 58*d1d35e2fSjeremylt CeedQFunctionAddInput(qf_setup_mass, "weight", 1, CEED_EVAL_WEIGHT); 593bd813ffSjeremylt CeedQFunctionAddOutput(qf_setup_mass, "qdata", 1, CEED_EVAL_NONE); 603bd813ffSjeremylt 613bd813ffSjeremylt // Operator - setup mass 623bd813ffSjeremylt CeedOperatorCreate(ceed, qf_setup_mass, CEED_QFUNCTION_NONE, 633bd813ffSjeremylt CEED_QFUNCTION_NONE, &op_setup_mass); 64*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "dx", elem_restr_x_i, basis_x, 653bd813ffSjeremylt CEED_VECTOR_ACTIVE); 66*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "weight", CEED_ELEMRESTRICTION_NONE, 67*d1d35e2fSjeremylt basis_x, 68a8d32208Sjeremylt CEED_VECTOR_NONE); 69*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "qdata", elem_restr_qd_i, 703bd813ffSjeremylt CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 713bd813ffSjeremylt 723bd813ffSjeremylt // Apply Setup Operator 73*d1d35e2fSjeremylt CeedOperatorApply(op_setup_mass, X, q_data_mass, CEED_REQUEST_IMMEDIATE); 743bd813ffSjeremylt 753bd813ffSjeremylt // QFunction - apply 763bd813ffSjeremylt CeedQFunctionCreateInterior(ceed, 1, apply, apply_loc, &qf_apply); 773bd813ffSjeremylt CeedQFunctionAddInput(qf_apply, "u", 1, CEED_EVAL_INTERP); 783bd813ffSjeremylt CeedQFunctionAddInput(qf_apply, "qdata_mass", 1, CEED_EVAL_NONE); 793bd813ffSjeremylt CeedQFunctionAddOutput(qf_apply, "v", 1, CEED_EVAL_INTERP); 803bd813ffSjeremylt 813bd813ffSjeremylt // Operator - apply 823bd813ffSjeremylt CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, 833bd813ffSjeremylt &op_apply); 84*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "u", elem_restr_u_i, basis_u, 85*d1d35e2fSjeremylt CEED_VECTOR_ACTIVE); 86*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "qdata_mass", elem_restr_qd_i, 87*d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, q_data_mass); 88*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "v", elem_restr_u_i, basis_u, 89*d1d35e2fSjeremylt CEED_VECTOR_ACTIVE); 903bd813ffSjeremylt 913bd813ffSjeremylt // Apply original operator 92*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &U); 933bd813ffSjeremylt CeedVectorSetValue(U, 1.0); 94*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &V); 953bd813ffSjeremylt CeedVectorSetValue(V, 0.0); 963bd813ffSjeremylt CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE); 973bd813ffSjeremylt 983bd813ffSjeremylt // Create FDM element inverse 993bd813ffSjeremylt CeedOperatorCreateFDMElementInverse(op_apply, &op_inv, CEED_REQUEST_IMMEDIATE); 1003bd813ffSjeremylt 1013bd813ffSjeremylt // Apply FDM element inverse 1023bd813ffSjeremylt CeedOperatorApply(op_inv, V, U, CEED_REQUEST_IMMEDIATE); 1033bd813ffSjeremylt 1043bd813ffSjeremylt // Check output 1053bd813ffSjeremylt CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); 106*d1d35e2fSjeremylt for (int i=0; i<num_dofs; i++) 1074596745bSJed Brown if (fabs(u[i] - 1.0) > 5e-14) 1083bd813ffSjeremylt // LCOV_EXCL_START 1094596745bSJed Brown printf("[%d] Error in inverse: %e - 1.0 = %e\n", i, u[i], u[i] - 1.); 1103bd813ffSjeremylt // LCOV_EXCL_STOP 1113bd813ffSjeremylt CeedVectorRestoreArrayRead(U, &u); 1123bd813ffSjeremylt 1133bd813ffSjeremylt // Cleanup 1143bd813ffSjeremylt CeedQFunctionDestroy(&qf_setup_mass); 1153bd813ffSjeremylt CeedQFunctionDestroy(&qf_apply); 1163bd813ffSjeremylt CeedOperatorDestroy(&op_setup_mass); 1173bd813ffSjeremylt CeedOperatorDestroy(&op_apply); 1183bd813ffSjeremylt CeedOperatorDestroy(&op_inv); 119*d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_u_i); 120*d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_x_i); 121*d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_qd_i); 122*d1d35e2fSjeremylt CeedBasisDestroy(&basis_u); 123*d1d35e2fSjeremylt CeedBasisDestroy(&basis_x); 1243bd813ffSjeremylt CeedVectorDestroy(&X); 125*d1d35e2fSjeremylt CeedVectorDestroy(&q_data_mass); 1263bd813ffSjeremylt CeedVectorDestroy(&U); 1273bd813ffSjeremylt CeedVectorDestroy(&V); 1283bd813ffSjeremylt CeedDestroy(&ceed); 1293bd813ffSjeremylt return 0; 1303bd813ffSjeremylt } 131