13bd813ffSjeremylt /// @file 23bd813ffSjeremylt /// Test creation and use of FDM element inverse 33bd813ffSjeremylt /// \test Test creation and use of FDM element inverse 43bd813ffSjeremylt #include "t540-operator.h" 53bd813ffSjeremylt 6*2b730f8bSJeremy L Thompson #include <ceed.h> 7*2b730f8bSJeremy L Thompson #include <math.h> 8*2b730f8bSJeremy L Thompson #include <stdlib.h> 9*2b730f8bSJeremy L Thompson 103bd813ffSjeremylt int main(int argc, char **argv) { 113bd813ffSjeremylt Ceed ceed; 12d1d35e2fSjeremylt CeedElemRestriction elem_restr_x_i, elem_restr_u_i, elem_restr_qd_i; 13d1d35e2fSjeremylt CeedBasis basis_x, basis_u; 143bd813ffSjeremylt CeedQFunction qf_setup_mass, qf_apply; 153bd813ffSjeremylt CeedOperator op_setup_mass, op_apply, op_inv; 16d1d35e2fSjeremylt CeedVector q_data_mass, X, U, V; 17d1d35e2fSjeremylt CeedInt num_elem = 1, P = 4, Q = 5, dim = 2; 18d1d35e2fSjeremylt CeedInt num_dofs = P * P, num_qpts = num_elem * Q * Q; 19d1d35e2fSjeremylt CeedScalar x[dim * num_elem * (2 * 2)]; 203bd813ffSjeremylt const CeedScalar *u; 213bd813ffSjeremylt 223bd813ffSjeremylt CeedInit(argv[1], &ceed); 233bd813ffSjeremylt 243bd813ffSjeremylt // DoF Coordinates 25*2b730f8bSJeremy L Thompson for (CeedInt i = 0; i < 2; i++) { 263bd813ffSjeremylt for (CeedInt j = 0; j < 2; j++) { 273bd813ffSjeremylt x[i + j * 2 + 0 * 4] = i; 283bd813ffSjeremylt x[i + j * 2 + 1 * 4] = j; 293bd813ffSjeremylt } 30*2b730f8bSJeremy L Thompson } 31d1d35e2fSjeremylt CeedVectorCreate(ceed, dim * num_elem * (2 * 2), &X); 323bd813ffSjeremylt CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x); 333bd813ffSjeremylt 343bd813ffSjeremylt // Qdata Vector 35d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts, &q_data_mass); 363bd813ffSjeremylt 373bd813ffSjeremylt // Element Setup 383bd813ffSjeremylt 393bd813ffSjeremylt // Restrictions 40d1d35e2fSjeremylt CeedInt strides_x[3] = {1, 2 * 2, 2 * 2 * dim}; 41*2b730f8bSJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem, 2 * 2, dim, dim * num_elem * 2 * 2, strides_x, &elem_restr_x_i); 423bd813ffSjeremylt 43d1d35e2fSjeremylt CeedInt strides_u[3] = {1, P * P, P * P}; 44*2b730f8bSJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem, P * P, 1, num_dofs, strides_u, &elem_restr_u_i); 453bd813ffSjeremylt 46d1d35e2fSjeremylt CeedInt strides_qd[3] = {1, Q * Q, Q * Q}; 47*2b730f8bSJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem, Q * Q, 1, num_qpts, strides_qd, &elem_restr_qd_i); 483bd813ffSjeremylt 493bd813ffSjeremylt // Bases 50d1d35e2fSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, Q, CEED_GAUSS, &basis_x); 51d1d35e2fSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P, Q, CEED_GAUSS, &basis_u); 523bd813ffSjeremylt 533bd813ffSjeremylt // QFunction - setup mass 54*2b730f8bSJeremy L Thompson CeedQFunctionCreateInterior(ceed, 1, setup_mass, setup_mass_loc, &qf_setup_mass); 553bd813ffSjeremylt CeedQFunctionAddInput(qf_setup_mass, "dx", dim * dim, CEED_EVAL_GRAD); 56d1d35e2fSjeremylt CeedQFunctionAddInput(qf_setup_mass, "weight", 1, CEED_EVAL_WEIGHT); 573bd813ffSjeremylt CeedQFunctionAddOutput(qf_setup_mass, "qdata", 1, CEED_EVAL_NONE); 583bd813ffSjeremylt 593bd813ffSjeremylt // Operator - setup mass 60*2b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_setup_mass, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_setup_mass); 61*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_mass, "dx", elem_restr_x_i, basis_x, CEED_VECTOR_ACTIVE); 62*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_mass, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE); 63*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_mass, "qdata", elem_restr_qd_i, CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 643bd813ffSjeremylt 653bd813ffSjeremylt // Apply Setup Operator 66d1d35e2fSjeremylt CeedOperatorApply(op_setup_mass, X, q_data_mass, CEED_REQUEST_IMMEDIATE); 673bd813ffSjeremylt 683bd813ffSjeremylt // QFunction - apply 693bd813ffSjeremylt CeedQFunctionCreateInterior(ceed, 1, apply, apply_loc, &qf_apply); 703bd813ffSjeremylt CeedQFunctionAddInput(qf_apply, "u", 1, CEED_EVAL_INTERP); 71a61c78d6SJeremy L Thompson CeedQFunctionAddInput(qf_apply, "mass qdata", 1, CEED_EVAL_NONE); 723bd813ffSjeremylt CeedQFunctionAddOutput(qf_apply, "v", 1, CEED_EVAL_INTERP); 733bd813ffSjeremylt 743bd813ffSjeremylt // Operator - apply 75*2b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_apply); 76*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_apply, "u", elem_restr_u_i, basis_u, CEED_VECTOR_ACTIVE); 77*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_apply, "mass qdata", elem_restr_qd_i, CEED_BASIS_COLLOCATED, q_data_mass); 78*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_apply, "v", elem_restr_u_i, basis_u, CEED_VECTOR_ACTIVE); 793bd813ffSjeremylt 803bd813ffSjeremylt // Apply original operator 81d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &U); 823bd813ffSjeremylt CeedVectorSetValue(U, 1.0); 83d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &V); 843bd813ffSjeremylt CeedVectorSetValue(V, 0.0); 853bd813ffSjeremylt CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE); 863bd813ffSjeremylt 873bd813ffSjeremylt // Create FDM element inverse 883bd813ffSjeremylt CeedOperatorCreateFDMElementInverse(op_apply, &op_inv, CEED_REQUEST_IMMEDIATE); 893bd813ffSjeremylt 903bd813ffSjeremylt // Apply FDM element inverse 913bd813ffSjeremylt CeedOperatorApply(op_inv, V, U, CEED_REQUEST_IMMEDIATE); 923bd813ffSjeremylt 933bd813ffSjeremylt // Check output 943bd813ffSjeremylt CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); 95*2b730f8bSJeremy L Thompson for (int i = 0; i < num_dofs; i++) { 96*2b730f8bSJeremy L Thompson if (fabs(u[i] - 1.0) > 500. * CEED_EPSILON) printf("[%" CeedInt_FMT "] Error in inverse: %e - 1.0 = %e\n", i, u[i], u[i] - 1.); 97*2b730f8bSJeremy L Thompson } 983bd813ffSjeremylt CeedVectorRestoreArrayRead(U, &u); 993bd813ffSjeremylt 1003bd813ffSjeremylt // Cleanup 1013bd813ffSjeremylt CeedQFunctionDestroy(&qf_setup_mass); 1023bd813ffSjeremylt CeedQFunctionDestroy(&qf_apply); 1033bd813ffSjeremylt CeedOperatorDestroy(&op_setup_mass); 1043bd813ffSjeremylt CeedOperatorDestroy(&op_apply); 1053bd813ffSjeremylt CeedOperatorDestroy(&op_inv); 106d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_u_i); 107d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_x_i); 108d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_qd_i); 109d1d35e2fSjeremylt CeedBasisDestroy(&basis_u); 110d1d35e2fSjeremylt CeedBasisDestroy(&basis_x); 1113bd813ffSjeremylt CeedVectorDestroy(&X); 112d1d35e2fSjeremylt CeedVectorDestroy(&q_data_mass); 1133bd813ffSjeremylt CeedVectorDestroy(&U); 1143bd813ffSjeremylt CeedVectorDestroy(&V); 1153bd813ffSjeremylt CeedDestroy(&ceed); 1163bd813ffSjeremylt return 0; 1173bd813ffSjeremylt } 118