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; 11d1d35e2fSjeremylt CeedElemRestriction elem_restr_x_i, elem_restr_u_i, elem_restr_qd_i; 12d1d35e2fSjeremylt CeedBasis basis_x, basis_u; 133bd813ffSjeremylt CeedQFunction qf_setup_mass, qf_apply; 143bd813ffSjeremylt CeedOperator op_setup_mass, op_apply, op_inv; 15d1d35e2fSjeremylt CeedVector q_data_mass, X, U, V; 16d1d35e2fSjeremylt CeedInt num_elem = 1, P = 4, Q = 5, dim = 2; 17d1d35e2fSjeremylt CeedInt num_dofs = P*P, num_qpts = num_elem*Q*Q; 18d1d35e2fSjeremylt 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 } 29d1d35e2fSjeremylt CeedVectorCreate(ceed, dim*num_elem*(2*2), &X); 303bd813ffSjeremylt CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x); 313bd813ffSjeremylt 323bd813ffSjeremylt // Qdata Vector 33d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts, &q_data_mass); 343bd813ffSjeremylt 353bd813ffSjeremylt // Element Setup 363bd813ffSjeremylt 373bd813ffSjeremylt // Restrictions 38d1d35e2fSjeremylt CeedInt strides_x[3] = {1, 2*2, 2*2*dim}; 39d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, 2*2, dim, dim*num_elem*2*2, 40d1d35e2fSjeremylt strides_x, &elem_restr_x_i); 413bd813ffSjeremylt 42d1d35e2fSjeremylt CeedInt strides_u[3] = {1, P*P, P*P}; 43d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, P*P, 1, num_dofs, strides_u, 44d1d35e2fSjeremylt &elem_restr_u_i); 453bd813ffSjeremylt 46d1d35e2fSjeremylt CeedInt strides_qd[3] = {1, Q*Q, Q*Q}; 47d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, Q*Q, 1, num_qpts, strides_qd, 48d1d35e2fSjeremylt &elem_restr_qd_i); 493bd813ffSjeremylt 503bd813ffSjeremylt // Bases 51d1d35e2fSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, Q, CEED_GAUSS, &basis_x); 52d1d35e2fSjeremylt 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); 58d1d35e2fSjeremylt 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); 64d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "dx", elem_restr_x_i, basis_x, 653bd813ffSjeremylt CEED_VECTOR_ACTIVE); 66d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "weight", CEED_ELEMRESTRICTION_NONE, 67*15ed3f7dSjeremylt basis_x, CEED_VECTOR_NONE); 68d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "qdata", elem_restr_qd_i, 693bd813ffSjeremylt CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 703bd813ffSjeremylt 713bd813ffSjeremylt // Apply Setup Operator 72d1d35e2fSjeremylt CeedOperatorApply(op_setup_mass, X, q_data_mass, CEED_REQUEST_IMMEDIATE); 733bd813ffSjeremylt 743bd813ffSjeremylt // QFunction - apply 753bd813ffSjeremylt CeedQFunctionCreateInterior(ceed, 1, apply, apply_loc, &qf_apply); 763bd813ffSjeremylt CeedQFunctionAddInput(qf_apply, "u", 1, CEED_EVAL_INTERP); 773bd813ffSjeremylt CeedQFunctionAddInput(qf_apply, "qdata_mass", 1, CEED_EVAL_NONE); 783bd813ffSjeremylt CeedQFunctionAddOutput(qf_apply, "v", 1, CEED_EVAL_INTERP); 793bd813ffSjeremylt 803bd813ffSjeremylt // Operator - apply 813bd813ffSjeremylt CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, 823bd813ffSjeremylt &op_apply); 83d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "u", elem_restr_u_i, basis_u, 84d1d35e2fSjeremylt CEED_VECTOR_ACTIVE); 85d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "qdata_mass", elem_restr_qd_i, 86d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, q_data_mass); 87d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "v", elem_restr_u_i, basis_u, 88d1d35e2fSjeremylt CEED_VECTOR_ACTIVE); 893bd813ffSjeremylt 903bd813ffSjeremylt // Apply original operator 91d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &U); 923bd813ffSjeremylt CeedVectorSetValue(U, 1.0); 93d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &V); 943bd813ffSjeremylt CeedVectorSetValue(V, 0.0); 953bd813ffSjeremylt CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE); 963bd813ffSjeremylt 973bd813ffSjeremylt // Create FDM element inverse 983bd813ffSjeremylt CeedOperatorCreateFDMElementInverse(op_apply, &op_inv, CEED_REQUEST_IMMEDIATE); 993bd813ffSjeremylt 1003bd813ffSjeremylt // Apply FDM element inverse 1013bd813ffSjeremylt CeedOperatorApply(op_inv, V, U, CEED_REQUEST_IMMEDIATE); 1023bd813ffSjeremylt 1033bd813ffSjeremylt // Check output 1043bd813ffSjeremylt CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); 105d1d35e2fSjeremylt for (int i=0; i<num_dofs; i++) 1064596745bSJed Brown if (fabs(u[i] - 1.0) > 5e-14) 1073bd813ffSjeremylt // LCOV_EXCL_START 1084596745bSJed Brown printf("[%d] Error in inverse: %e - 1.0 = %e\n", i, u[i], u[i] - 1.); 1093bd813ffSjeremylt // LCOV_EXCL_STOP 1103bd813ffSjeremylt CeedVectorRestoreArrayRead(U, &u); 1113bd813ffSjeremylt 1123bd813ffSjeremylt // Cleanup 1133bd813ffSjeremylt CeedQFunctionDestroy(&qf_setup_mass); 1143bd813ffSjeremylt CeedQFunctionDestroy(&qf_apply); 1153bd813ffSjeremylt CeedOperatorDestroy(&op_setup_mass); 1163bd813ffSjeremylt CeedOperatorDestroy(&op_apply); 1173bd813ffSjeremylt CeedOperatorDestroy(&op_inv); 118d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_u_i); 119d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_x_i); 120d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_qd_i); 121d1d35e2fSjeremylt CeedBasisDestroy(&basis_u); 122d1d35e2fSjeremylt CeedBasisDestroy(&basis_x); 1233bd813ffSjeremylt CeedVectorDestroy(&X); 124d1d35e2fSjeremylt CeedVectorDestroy(&q_data_mass); 1253bd813ffSjeremylt CeedVectorDestroy(&U); 1263bd813ffSjeremylt CeedVectorDestroy(&V); 1273bd813ffSjeremylt CeedDestroy(&ceed); 1283bd813ffSjeremylt return 0; 1293bd813ffSjeremylt } 130