1e83e87a5Sjeremylt #include "../include/matops.h" 22b730f8bSJeremy L Thompson 3e83e87a5Sjeremylt #include "../include/petscutils.h" 4e83e87a5Sjeremylt 5e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 66c88e6a2Srezgarshakeri // Setup apply operator context data 76c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 82b730f8bSJeremy L Thompson PetscErrorCode SetupApplyOperatorCtx(MPI_Comm comm, DM dm, Ceed ceed, CeedData ceed_data, Vec X_loc, OperatorApplyContext op_apply_ctx) { 96c88e6a2Srezgarshakeri PetscFunctionBeginUser; 106c88e6a2Srezgarshakeri 116c88e6a2Srezgarshakeri op_apply_ctx->comm = comm; 126c88e6a2Srezgarshakeri op_apply_ctx->dm = dm; 136c88e6a2Srezgarshakeri op_apply_ctx->X_loc = X_loc; 142b730f8bSJeremy L Thompson PetscCall(VecDuplicate(X_loc, &op_apply_ctx->Y_loc)); 156c88e6a2Srezgarshakeri op_apply_ctx->x_ceed = ceed_data->x_ceed; 166c88e6a2Srezgarshakeri op_apply_ctx->y_ceed = ceed_data->y_ceed; 176c88e6a2Srezgarshakeri op_apply_ctx->op = ceed_data->op_apply; 186c88e6a2Srezgarshakeri op_apply_ctx->ceed = ceed; 192b730f8bSJeremy L Thompson 20*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 216c88e6a2Srezgarshakeri } 226c88e6a2Srezgarshakeri 236c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 246c88e6a2Srezgarshakeri // Setup error operator context data 256c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 262b730f8bSJeremy L Thompson PetscErrorCode SetupErrorOperatorCtx(MPI_Comm comm, DM dm, Ceed ceed, CeedData ceed_data, Vec X_loc, CeedOperator op_error, 276c88e6a2Srezgarshakeri OperatorApplyContext op_error_ctx) { 286c88e6a2Srezgarshakeri PetscFunctionBeginUser; 296c88e6a2Srezgarshakeri 306c88e6a2Srezgarshakeri op_error_ctx->comm = comm; 316c88e6a2Srezgarshakeri op_error_ctx->dm = dm; 326c88e6a2Srezgarshakeri op_error_ctx->X_loc = X_loc; 332b730f8bSJeremy L Thompson PetscCall(VecDuplicate(X_loc, &op_error_ctx->Y_loc)); 346c88e6a2Srezgarshakeri op_error_ctx->x_ceed = ceed_data->x_ceed; 356c88e6a2Srezgarshakeri op_error_ctx->y_ceed = ceed_data->y_ceed; 366c88e6a2Srezgarshakeri op_error_ctx->op = op_error; 376c88e6a2Srezgarshakeri op_error_ctx->ceed = ceed; 382b730f8bSJeremy L Thompson 39*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 406c88e6a2Srezgarshakeri } 416c88e6a2Srezgarshakeri 426c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 43e83e87a5Sjeremylt // This function returns the computed diagonal of the operator 44e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 45e83e87a5Sjeremylt PetscErrorCode MatGetDiag(Mat A, Vec D) { 46d4d45553Srezgarshakeri OperatorApplyContext op_apply_ctx; 47e83e87a5Sjeremylt 48e83e87a5Sjeremylt PetscFunctionBeginUser; 49e83e87a5Sjeremylt 502b730f8bSJeremy L Thompson PetscCall(MatShellGetContext(A, &op_apply_ctx)); 51e83e87a5Sjeremylt 52e83e87a5Sjeremylt // Compute Diagonal via libCEED 53f1c40530SJeremy L Thompson PetscScalar *y; 549b072555Sjeremylt PetscMemType mem_type; 55e83e87a5Sjeremylt 56e83e87a5Sjeremylt // -- Place PETSc vector in libCEED vector 572b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &mem_type)); 582b730f8bSJeremy L Thompson CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), CEED_USE_POINTER, y); 59e83e87a5Sjeremylt 60e83e87a5Sjeremylt // -- Compute Diagonal 612b730f8bSJeremy L Thompson CeedOperatorLinearAssembleDiagonal(op_apply_ctx->op, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE); 62e83e87a5Sjeremylt 63e83e87a5Sjeremylt // -- Local-to-Global 64d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), NULL); 652b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y)); 662b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(D)); 672b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, D)); 68e83e87a5Sjeremylt 69*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 70e83e87a5Sjeremylt }; 71e83e87a5Sjeremylt 72e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 73ea61e9acSJeremy L Thompson // This function uses libCEED to compute the action of the Laplacian with Dirichlet boundary conditions 74e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 752b730f8bSJeremy L Thompson PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, OperatorApplyContext op_apply_ctx) { 76e83e87a5Sjeremylt PetscScalar *x, *y; 779b072555Sjeremylt PetscMemType x_mem_type, y_mem_type; 78e83e87a5Sjeremylt 79e83e87a5Sjeremylt PetscFunctionBeginUser; 80e83e87a5Sjeremylt 81e83e87a5Sjeremylt // Global-to-local 822b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(op_apply_ctx->dm, X, INSERT_VALUES, op_apply_ctx->X_loc)); 83e83e87a5Sjeremylt 84e83e87a5Sjeremylt // Setup libCEED vectors 852b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x, &x_mem_type)); 862b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &y_mem_type)); 872b730f8bSJeremy L Thompson CeedVectorSetArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x); 882b730f8bSJeremy L Thompson CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y); 89e83e87a5Sjeremylt 90e83e87a5Sjeremylt // Apply libCEED operator 912b730f8bSJeremy L Thompson CeedOperatorApply(op_apply_ctx->op, op_apply_ctx->x_ceed, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE); 92e83e87a5Sjeremylt 93e83e87a5Sjeremylt // Restore PETSc vectors 94d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), NULL); 95d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), NULL); 962b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x)); 972b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y)); 98e83e87a5Sjeremylt 99e83e87a5Sjeremylt // Local-to-global 1002b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y)); 1012b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, Y)); 102e83e87a5Sjeremylt 103*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 104e83e87a5Sjeremylt }; 105e83e87a5Sjeremylt 106e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 107e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell 108e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 109e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 110d4d45553Srezgarshakeri OperatorApplyContext op_apply_ctx; 111e83e87a5Sjeremylt 112e83e87a5Sjeremylt PetscFunctionBeginUser; 113e83e87a5Sjeremylt 1142b730f8bSJeremy L Thompson PetscCall(MatShellGetContext(A, &op_apply_ctx)); 115e83e87a5Sjeremylt 116e83e87a5Sjeremylt // libCEED for local action of residual evaluator 1172b730f8bSJeremy L Thompson PetscCall(ApplyLocal_Ceed(X, Y, op_apply_ctx)); 118e83e87a5Sjeremylt 119*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 120e83e87a5Sjeremylt }; 121e83e87a5Sjeremylt 122e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 123e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator 124e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 125e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) { 126d4d45553Srezgarshakeri ProlongRestrContext pr_restr_ctx; 127e83e87a5Sjeremylt PetscScalar *c, *f; 1289b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 129e83e87a5Sjeremylt 130e83e87a5Sjeremylt PetscFunctionBeginUser; 131e83e87a5Sjeremylt 1322b730f8bSJeremy L Thompson PetscCall(MatShellGetContext(A, &pr_restr_ctx)); 133e83e87a5Sjeremylt 134e83e87a5Sjeremylt // Global-to-local 1352b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_c)); 1362b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(pr_restr_ctx->dmc, X, INSERT_VALUES, pr_restr_ctx->loc_vec_c)); 137e83e87a5Sjeremylt 138e83e87a5Sjeremylt // Setup libCEED vectors 1392b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c, &c_mem_type)); 1402b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_f, &f, &f_mem_type)); 1412b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c); 1422b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f); 143e83e87a5Sjeremylt 144e83e87a5Sjeremylt // Apply libCEED operator 1452b730f8bSJeremy L Thompson CeedOperatorApply(pr_restr_ctx->op_prolong, pr_restr_ctx->ceed_vec_c, pr_restr_ctx->ceed_vec_f, CEED_REQUEST_IMMEDIATE); 146e83e87a5Sjeremylt 147e83e87a5Sjeremylt // Restore PETSc vectors 148d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 149d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 1502b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c)); 1512b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_f, &f)); 152e83e87a5Sjeremylt 153e83e87a5Sjeremylt // Multiplicity 1542b730f8bSJeremy L Thompson PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec)); 155e83e87a5Sjeremylt 156e83e87a5Sjeremylt // Local-to-global 1572b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y)); 1582b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(pr_restr_ctx->dmf, pr_restr_ctx->loc_vec_f, ADD_VALUES, Y)); 159e83e87a5Sjeremylt 160*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 161e83e87a5Sjeremylt }; 162e83e87a5Sjeremylt 163e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 164e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator 165e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 166e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) { 167d4d45553Srezgarshakeri ProlongRestrContext pr_restr_ctx; 168e83e87a5Sjeremylt PetscScalar *c, *f; 1699b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 170e83e87a5Sjeremylt 171e83e87a5Sjeremylt PetscFunctionBeginUser; 172e83e87a5Sjeremylt 1732b730f8bSJeremy L Thompson PetscCall(MatShellGetContext(A, &pr_restr_ctx)); 174e83e87a5Sjeremylt 175e83e87a5Sjeremylt // Global-to-local 1762b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_f)); 1772b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(pr_restr_ctx->dmf, X, INSERT_VALUES, pr_restr_ctx->loc_vec_f)); 178e83e87a5Sjeremylt 179e83e87a5Sjeremylt // Multiplicity 1802b730f8bSJeremy L Thompson PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec)); 181e83e87a5Sjeremylt 182e83e87a5Sjeremylt // Setup libCEED vectors 1832b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f, &f_mem_type)); 1842b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_c, &c, &c_mem_type)); 1852b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f); 1862b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c); 187e83e87a5Sjeremylt 188e83e87a5Sjeremylt // Apply CEED operator 1892b730f8bSJeremy L Thompson CeedOperatorApply(pr_restr_ctx->op_restrict, pr_restr_ctx->ceed_vec_f, pr_restr_ctx->ceed_vec_c, CEED_REQUEST_IMMEDIATE); 190e83e87a5Sjeremylt 191e83e87a5Sjeremylt // Restore PETSc vectors 192d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 193d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 1942b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f)); 1952b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_c, &c)); 196e83e87a5Sjeremylt 197e83e87a5Sjeremylt // Local-to-global 1982b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y)); 1992b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(pr_restr_ctx->dmc, pr_restr_ctx->loc_vec_c, ADD_VALUES, Y)); 200e83e87a5Sjeremylt 201*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 202e83e87a5Sjeremylt }; 203e83e87a5Sjeremylt 204e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 205e83e87a5Sjeremylt // This function calculates the error in the final solution 206e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 2072b730f8bSJeremy L Thompson PetscErrorCode ComputeL2Error(Vec X, PetscScalar *l2_error, OperatorApplyContext op_error_ctx) { 20838f32c05Srezgarshakeri Vec E; 209e83e87a5Sjeremylt PetscFunctionBeginUser; 21038f32c05Srezgarshakeri PetscCall(VecDuplicate(X, &E)); 21138f32c05Srezgarshakeri PetscCall(ApplyLocal_Ceed(X, E, op_error_ctx)); 21238f32c05Srezgarshakeri PetscScalar error_sq = 1.0; 21338f32c05Srezgarshakeri PetscCall(VecSum(E, &error_sq)); 21438f32c05Srezgarshakeri *l2_error = sqrt(error_sq); 215e83e87a5Sjeremylt 216*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 217e83e87a5Sjeremylt }; 218e83e87a5Sjeremylt 219e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 220