1e83e87a5Sjeremylt #include "../include/matops.h" 2*2b730f8bSJeremy L Thompson 3e83e87a5Sjeremylt #include "../include/petscutils.h" 4e83e87a5Sjeremylt 5e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 66c88e6a2Srezgarshakeri // Setup apply operator context data 76c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 8*2b730f8bSJeremy 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; 14*2b730f8bSJeremy 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; 19*2b730f8bSJeremy L Thompson 206c88e6a2Srezgarshakeri PetscFunctionReturn(0); 216c88e6a2Srezgarshakeri } 226c88e6a2Srezgarshakeri 236c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 246c88e6a2Srezgarshakeri // Setup error operator context data 256c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 26*2b730f8bSJeremy 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; 33*2b730f8bSJeremy 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; 38*2b730f8bSJeremy L Thompson 396c88e6a2Srezgarshakeri PetscFunctionReturn(0); 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 50*2b730f8bSJeremy 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 57*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &mem_type)); 58*2b730f8bSJeremy L Thompson CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), CEED_USE_POINTER, y); 59e83e87a5Sjeremylt 60e83e87a5Sjeremylt // -- Compute Diagonal 61*2b730f8bSJeremy 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); 65*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y)); 66*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(D)); 67*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, D)); 68e83e87a5Sjeremylt 69e83e87a5Sjeremylt PetscFunctionReturn(0); 70e83e87a5Sjeremylt }; 71e83e87a5Sjeremylt 72e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 73e83e87a5Sjeremylt // This function uses libCEED to compute the action of the Laplacian with 74e83e87a5Sjeremylt // Dirichlet boundary conditions 75e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 76*2b730f8bSJeremy L Thompson PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, OperatorApplyContext op_apply_ctx) { 77e83e87a5Sjeremylt PetscScalar *x, *y; 789b072555Sjeremylt PetscMemType x_mem_type, y_mem_type; 79e83e87a5Sjeremylt 80e83e87a5Sjeremylt PetscFunctionBeginUser; 81e83e87a5Sjeremylt 82e83e87a5Sjeremylt // Global-to-local 83*2b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(op_apply_ctx->dm, X, INSERT_VALUES, op_apply_ctx->X_loc)); 84e83e87a5Sjeremylt 85e83e87a5Sjeremylt // Setup libCEED vectors 86*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x, &x_mem_type)); 87*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &y_mem_type)); 88*2b730f8bSJeremy L Thompson CeedVectorSetArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x); 89*2b730f8bSJeremy L Thompson CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y); 90e83e87a5Sjeremylt 91e83e87a5Sjeremylt // Apply libCEED operator 92*2b730f8bSJeremy L Thompson CeedOperatorApply(op_apply_ctx->op, op_apply_ctx->x_ceed, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE); 93e83e87a5Sjeremylt 94e83e87a5Sjeremylt // Restore PETSc vectors 95d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), NULL); 96d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), NULL); 97*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x)); 98*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y)); 99e83e87a5Sjeremylt 100e83e87a5Sjeremylt // Local-to-global 101*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y)); 102*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, Y)); 103e83e87a5Sjeremylt 104e83e87a5Sjeremylt PetscFunctionReturn(0); 105e83e87a5Sjeremylt }; 106e83e87a5Sjeremylt 107e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 108e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell 109e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 110e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 111d4d45553Srezgarshakeri OperatorApplyContext op_apply_ctx; 112e83e87a5Sjeremylt 113e83e87a5Sjeremylt PetscFunctionBeginUser; 114e83e87a5Sjeremylt 115*2b730f8bSJeremy L Thompson PetscCall(MatShellGetContext(A, &op_apply_ctx)); 116e83e87a5Sjeremylt 117e83e87a5Sjeremylt // libCEED for local action of residual evaluator 118*2b730f8bSJeremy L Thompson PetscCall(ApplyLocal_Ceed(X, Y, op_apply_ctx)); 119e83e87a5Sjeremylt 120e83e87a5Sjeremylt PetscFunctionReturn(0); 121e83e87a5Sjeremylt }; 122e83e87a5Sjeremylt 123e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 124e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator 125e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 126e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) { 127d4d45553Srezgarshakeri ProlongRestrContext pr_restr_ctx; 128e83e87a5Sjeremylt PetscScalar *c, *f; 1299b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 130e83e87a5Sjeremylt 131e83e87a5Sjeremylt PetscFunctionBeginUser; 132e83e87a5Sjeremylt 133*2b730f8bSJeremy L Thompson PetscCall(MatShellGetContext(A, &pr_restr_ctx)); 134e83e87a5Sjeremylt 135e83e87a5Sjeremylt // Global-to-local 136*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_c)); 137*2b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(pr_restr_ctx->dmc, X, INSERT_VALUES, pr_restr_ctx->loc_vec_c)); 138e83e87a5Sjeremylt 139e83e87a5Sjeremylt // Setup libCEED vectors 140*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c, &c_mem_type)); 141*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_f, &f, &f_mem_type)); 142*2b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c); 143*2b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f); 144e83e87a5Sjeremylt 145e83e87a5Sjeremylt // Apply libCEED operator 146*2b730f8bSJeremy L Thompson CeedOperatorApply(pr_restr_ctx->op_prolong, pr_restr_ctx->ceed_vec_c, pr_restr_ctx->ceed_vec_f, CEED_REQUEST_IMMEDIATE); 147e83e87a5Sjeremylt 148e83e87a5Sjeremylt // Restore PETSc vectors 149d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 150d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 151*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c)); 152*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_f, &f)); 153e83e87a5Sjeremylt 154e83e87a5Sjeremylt // Multiplicity 155*2b730f8bSJeremy L Thompson PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec)); 156e83e87a5Sjeremylt 157e83e87a5Sjeremylt // Local-to-global 158*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y)); 159*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(pr_restr_ctx->dmf, pr_restr_ctx->loc_vec_f, ADD_VALUES, Y)); 160e83e87a5Sjeremylt 161e83e87a5Sjeremylt PetscFunctionReturn(0); 162e83e87a5Sjeremylt }; 163e83e87a5Sjeremylt 164e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 165e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator 166e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 167e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) { 168d4d45553Srezgarshakeri ProlongRestrContext pr_restr_ctx; 169e83e87a5Sjeremylt PetscScalar *c, *f; 1709b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 171e83e87a5Sjeremylt 172e83e87a5Sjeremylt PetscFunctionBeginUser; 173e83e87a5Sjeremylt 174*2b730f8bSJeremy L Thompson PetscCall(MatShellGetContext(A, &pr_restr_ctx)); 175e83e87a5Sjeremylt 176e83e87a5Sjeremylt // Global-to-local 177*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_f)); 178*2b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(pr_restr_ctx->dmf, X, INSERT_VALUES, pr_restr_ctx->loc_vec_f)); 179e83e87a5Sjeremylt 180e83e87a5Sjeremylt // Multiplicity 181*2b730f8bSJeremy L Thompson PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec)); 182e83e87a5Sjeremylt 183e83e87a5Sjeremylt // Setup libCEED vectors 184*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f, &f_mem_type)); 185*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_c, &c, &c_mem_type)); 186*2b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f); 187*2b730f8bSJeremy L Thompson CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c); 188e83e87a5Sjeremylt 189e83e87a5Sjeremylt // Apply CEED operator 190*2b730f8bSJeremy L Thompson CeedOperatorApply(pr_restr_ctx->op_restrict, pr_restr_ctx->ceed_vec_f, pr_restr_ctx->ceed_vec_c, CEED_REQUEST_IMMEDIATE); 191e83e87a5Sjeremylt 192e83e87a5Sjeremylt // Restore PETSc vectors 193d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 194d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 195*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f)); 196*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_c, &c)); 197e83e87a5Sjeremylt 198e83e87a5Sjeremylt // Local-to-global 199*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y)); 200*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(pr_restr_ctx->dmc, pr_restr_ctx->loc_vec_c, ADD_VALUES, Y)); 201e83e87a5Sjeremylt 202e83e87a5Sjeremylt PetscFunctionReturn(0); 203e83e87a5Sjeremylt }; 204e83e87a5Sjeremylt 205e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 206e83e87a5Sjeremylt // This function calculates the error in the final solution 207e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 208*2b730f8bSJeremy L Thompson PetscErrorCode ComputeL2Error(Vec X, PetscScalar *l2_error, OperatorApplyContext op_error_ctx) { 20938f32c05Srezgarshakeri Vec E; 210e83e87a5Sjeremylt PetscFunctionBeginUser; 21138f32c05Srezgarshakeri PetscCall(VecDuplicate(X, &E)); 21238f32c05Srezgarshakeri PetscCall(ApplyLocal_Ceed(X, E, op_error_ctx)); 21338f32c05Srezgarshakeri PetscScalar error_sq = 1.0; 21438f32c05Srezgarshakeri PetscCall(VecSum(E, &error_sq)); 21538f32c05Srezgarshakeri *l2_error = sqrt(error_sq); 216e83e87a5Sjeremylt 217e83e87a5Sjeremylt PetscFunctionReturn(0); 218e83e87a5Sjeremylt }; 219e83e87a5Sjeremylt 220e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 221