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; 113bd813ffSjeremylt CeedElemRestriction Erestrictxi, Erestrictui, Erestrictqi; 123bd813ffSjeremylt CeedBasis bx, bu; 133bd813ffSjeremylt CeedQFunction qf_setup_mass, qf_apply; 143bd813ffSjeremylt CeedOperator op_setup_mass, op_apply, op_inv; 153bd813ffSjeremylt CeedVector qdata_mass, X, U, V; 163bd813ffSjeremylt CeedInt nelem = 1, P = 4, Q = 5, dim = 2; 173bd813ffSjeremylt CeedInt ndofs = P*P, nqpts = nelem*Q*Q; 183bd813ffSjeremylt CeedScalar x[dim*nelem*(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 } 293bd813ffSjeremylt CeedVectorCreate(ceed, dim*nelem*(2*2), &X); 303bd813ffSjeremylt CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x); 313bd813ffSjeremylt 323bd813ffSjeremylt // Qdata Vector 333bd813ffSjeremylt CeedVectorCreate(ceed, nqpts, &qdata_mass); 343bd813ffSjeremylt 353bd813ffSjeremylt // Element Setup 363bd813ffSjeremylt 373bd813ffSjeremylt // Restrictions 387509a596Sjeremylt CeedInt stridesx[3] = {1, 2*2, 2*2*dim}; 397509a596Sjeremylt CeedElemRestrictionCreateStrided(ceed, nelem, 2*2, nelem*2*2, dim, stridesx, 403bd813ffSjeremylt &Erestrictxi); 413bd813ffSjeremylt 427509a596Sjeremylt CeedInt stridesu[3] = {1, P*P, P*P}; 437509a596Sjeremylt CeedElemRestrictionCreateStrided(ceed, nelem, P*P, ndofs, 1, stridesu, 44a8d32208Sjeremylt &Erestrictui); 453bd813ffSjeremylt 467509a596Sjeremylt CeedInt stridesq[3] = {1, Q*Q, Q*Q}; 477509a596Sjeremylt CeedElemRestrictionCreateStrided(ceed, nelem, Q*Q, nqpts, 1, stridesq, 48a8d32208Sjeremylt &Erestrictqi); 493bd813ffSjeremylt 503bd813ffSjeremylt // Bases 513bd813ffSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, Q, CEED_GAUSS, &bx); 523bd813ffSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P, Q, CEED_GAUSS, &bu); 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); 583bd813ffSjeremylt 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); 64a8d32208Sjeremylt CeedOperatorSetField(op_setup_mass, "dx", Erestrictxi, bx, 653bd813ffSjeremylt CEED_VECTOR_ACTIVE); 66*15910d16Sjeremylt CeedOperatorSetField(op_setup_mass, "_weight", CEED_ELEMRESTRICTION_NONE, bx, 67a8d32208Sjeremylt CEED_VECTOR_NONE); 68a8d32208Sjeremylt CeedOperatorSetField(op_setup_mass, "qdata", Erestrictqi, 693bd813ffSjeremylt CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 703bd813ffSjeremylt 713bd813ffSjeremylt // Apply Setup Operator 723bd813ffSjeremylt CeedOperatorApply(op_setup_mass, X, qdata_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); 83a8d32208Sjeremylt CeedOperatorSetField(op_apply, "u", Erestrictui, bu, CEED_VECTOR_ACTIVE); 84a8d32208Sjeremylt CeedOperatorSetField(op_apply, "qdata_mass", Erestrictqi, 853bd813ffSjeremylt CEED_BASIS_COLLOCATED, qdata_mass); 86a8d32208Sjeremylt CeedOperatorSetField(op_apply, "v", Erestrictui, bu, CEED_VECTOR_ACTIVE); 873bd813ffSjeremylt 883bd813ffSjeremylt // Apply original operator 893bd813ffSjeremylt CeedVectorCreate(ceed, ndofs, &U); 903bd813ffSjeremylt CeedVectorSetValue(U, 1.0); 913bd813ffSjeremylt CeedVectorCreate(ceed, ndofs, &V); 923bd813ffSjeremylt CeedVectorSetValue(V, 0.0); 933bd813ffSjeremylt CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE); 943bd813ffSjeremylt 953bd813ffSjeremylt // Create FDM element inverse 963bd813ffSjeremylt CeedOperatorCreateFDMElementInverse(op_apply, &op_inv, CEED_REQUEST_IMMEDIATE); 973bd813ffSjeremylt 983bd813ffSjeremylt // Apply FDM element inverse 993bd813ffSjeremylt CeedOperatorApply(op_inv, V, U, CEED_REQUEST_IMMEDIATE); 1003bd813ffSjeremylt 1013bd813ffSjeremylt // Check output 1023bd813ffSjeremylt CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); 1033bd813ffSjeremylt for (int i=0; i<ndofs; i++) 1043bd813ffSjeremylt if (fabs(u[i] - 1.0) > 1E-14) 1053bd813ffSjeremylt // LCOV_EXCL_START 1063bd813ffSjeremylt printf("[%d] Error in inverse: %f != 1.0\n", i, u[i]); 1073bd813ffSjeremylt // LCOV_EXCL_STOP 1083bd813ffSjeremylt CeedVectorRestoreArrayRead(U, &u); 1093bd813ffSjeremylt 1103bd813ffSjeremylt // Cleanup 1113bd813ffSjeremylt CeedQFunctionDestroy(&qf_setup_mass); 1123bd813ffSjeremylt CeedQFunctionDestroy(&qf_apply); 1133bd813ffSjeremylt CeedOperatorDestroy(&op_setup_mass); 1143bd813ffSjeremylt CeedOperatorDestroy(&op_apply); 1153bd813ffSjeremylt CeedOperatorDestroy(&op_inv); 1163bd813ffSjeremylt CeedElemRestrictionDestroy(&Erestrictui); 1173bd813ffSjeremylt CeedElemRestrictionDestroy(&Erestrictxi); 1183bd813ffSjeremylt CeedElemRestrictionDestroy(&Erestrictqi); 1193bd813ffSjeremylt CeedBasisDestroy(&bu); 1203bd813ffSjeremylt CeedBasisDestroy(&bx); 1213bd813ffSjeremylt CeedVectorDestroy(&X); 1223bd813ffSjeremylt CeedVectorDestroy(&qdata_mass); 1233bd813ffSjeremylt CeedVectorDestroy(&U); 1243bd813ffSjeremylt CeedVectorDestroy(&V); 1253bd813ffSjeremylt CeedDestroy(&ceed); 1263bd813ffSjeremylt return 0; 1273bd813ffSjeremylt } 128