1e83e87a5Sjeremylt #include "../include/matops.h" 2e83e87a5Sjeremylt #include "../include/petscutils.h" 3e83e87a5Sjeremylt 4e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 56c88e6a2Srezgarshakeri // Setup apply operator context data 66c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 76c88e6a2Srezgarshakeri PetscErrorCode SetupApplyOperatorCtx(MPI_Comm comm, DM dm, Ceed ceed, 86c88e6a2Srezgarshakeri CeedData ceed_data, Vec X_loc, 96c88e6a2Srezgarshakeri OperatorApplyContext op_apply_ctx) { 106c88e6a2Srezgarshakeri PetscErrorCode ierr; 116c88e6a2Srezgarshakeri PetscFunctionBeginUser; 126c88e6a2Srezgarshakeri 136c88e6a2Srezgarshakeri op_apply_ctx->comm = comm; 146c88e6a2Srezgarshakeri op_apply_ctx->dm = dm; 156c88e6a2Srezgarshakeri op_apply_ctx->X_loc = X_loc; 166c88e6a2Srezgarshakeri ierr = VecDuplicate(X_loc, &op_apply_ctx->Y_loc); CHKERRQ(ierr); 176c88e6a2Srezgarshakeri op_apply_ctx->x_ceed = ceed_data->x_ceed; 186c88e6a2Srezgarshakeri op_apply_ctx->y_ceed = ceed_data->y_ceed; 196c88e6a2Srezgarshakeri op_apply_ctx->op = ceed_data->op_apply; 206c88e6a2Srezgarshakeri op_apply_ctx->ceed = ceed; 216c88e6a2Srezgarshakeri PetscFunctionReturn(0); 226c88e6a2Srezgarshakeri } 236c88e6a2Srezgarshakeri 246c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 256c88e6a2Srezgarshakeri // Setup error operator context data 266c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 276c88e6a2Srezgarshakeri PetscErrorCode SetupErrorOperatorCtx(MPI_Comm comm, DM dm, Ceed ceed, 286c88e6a2Srezgarshakeri CeedData ceed_data, Vec X_loc, CeedOperator op_error, 296c88e6a2Srezgarshakeri OperatorApplyContext op_error_ctx) { 306c88e6a2Srezgarshakeri PetscErrorCode ierr; 316c88e6a2Srezgarshakeri PetscFunctionBeginUser; 326c88e6a2Srezgarshakeri 336c88e6a2Srezgarshakeri op_error_ctx->comm = comm; 346c88e6a2Srezgarshakeri op_error_ctx->dm = dm; 356c88e6a2Srezgarshakeri op_error_ctx->X_loc = X_loc; 366c88e6a2Srezgarshakeri ierr = VecDuplicate(X_loc, &op_error_ctx->Y_loc); CHKERRQ(ierr); 376c88e6a2Srezgarshakeri op_error_ctx->x_ceed = ceed_data->x_ceed; 386c88e6a2Srezgarshakeri op_error_ctx->y_ceed = ceed_data->y_ceed; 396c88e6a2Srezgarshakeri op_error_ctx->op = op_error; 406c88e6a2Srezgarshakeri op_error_ctx->ceed = ceed; 416c88e6a2Srezgarshakeri PetscFunctionReturn(0); 426c88e6a2Srezgarshakeri } 436c88e6a2Srezgarshakeri 446c88e6a2Srezgarshakeri // ----------------------------------------------------------------------------- 45e83e87a5Sjeremylt // This function returns the computed diagonal of the operator 46e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 47e83e87a5Sjeremylt PetscErrorCode MatGetDiag(Mat A, Vec D) { 48e83e87a5Sjeremylt PetscErrorCode ierr; 49d4d45553Srezgarshakeri OperatorApplyContext op_apply_ctx; 50e83e87a5Sjeremylt 51e83e87a5Sjeremylt PetscFunctionBeginUser; 52e83e87a5Sjeremylt 53d4d45553Srezgarshakeri ierr = MatShellGetContext(A, &op_apply_ctx); CHKERRQ(ierr); 54e83e87a5Sjeremylt 55e83e87a5Sjeremylt // Compute Diagonal via libCEED 56f1c40530SJeremy L Thompson PetscScalar *y; 579b072555Sjeremylt PetscMemType mem_type; 58e83e87a5Sjeremylt 59e83e87a5Sjeremylt // -- Place PETSc vector in libCEED vector 60d4d45553Srezgarshakeri ierr = VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &mem_type); CHKERRQ(ierr); 61d4d45553Srezgarshakeri CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), 62d4d45553Srezgarshakeri CEED_USE_POINTER, y); 63e83e87a5Sjeremylt 64e83e87a5Sjeremylt // -- Compute Diagonal 65d4d45553Srezgarshakeri CeedOperatorLinearAssembleDiagonal(op_apply_ctx->op, op_apply_ctx->y_ceed, 66e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 67e83e87a5Sjeremylt 68e83e87a5Sjeremylt // -- Local-to-Global 69d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), NULL); 70d4d45553Srezgarshakeri ierr = VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y); CHKERRQ(ierr); 71e83e87a5Sjeremylt ierr = VecZeroEntries(D); CHKERRQ(ierr); 72d4d45553Srezgarshakeri ierr = DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, D); 73d4d45553Srezgarshakeri CHKERRQ(ierr); 74e83e87a5Sjeremylt 75e83e87a5Sjeremylt PetscFunctionReturn(0); 76e83e87a5Sjeremylt }; 77e83e87a5Sjeremylt 78e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 79e83e87a5Sjeremylt // This function uses libCEED to compute the action of the Laplacian with 80e83e87a5Sjeremylt // Dirichlet boundary conditions 81e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 82d4d45553Srezgarshakeri PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, 83d4d45553Srezgarshakeri OperatorApplyContext op_apply_ctx) { 84e83e87a5Sjeremylt PetscErrorCode ierr; 85e83e87a5Sjeremylt PetscScalar *x, *y; 869b072555Sjeremylt PetscMemType x_mem_type, y_mem_type; 87e83e87a5Sjeremylt 88e83e87a5Sjeremylt PetscFunctionBeginUser; 89e83e87a5Sjeremylt 90e83e87a5Sjeremylt // Global-to-local 91d4d45553Srezgarshakeri ierr = DMGlobalToLocal(op_apply_ctx->dm, X, INSERT_VALUES, op_apply_ctx->X_loc); 92d4d45553Srezgarshakeri CHKERRQ(ierr); 93e83e87a5Sjeremylt 94e83e87a5Sjeremylt // Setup libCEED vectors 95d4d45553Srezgarshakeri ierr = VecGetArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x, 969b072555Sjeremylt &x_mem_type); CHKERRQ(ierr); 97d4d45553Srezgarshakeri ierr = VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &y_mem_type); 98d4d45553Srezgarshakeri CHKERRQ(ierr); 99d4d45553Srezgarshakeri CeedVectorSetArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), 100d4d45553Srezgarshakeri CEED_USE_POINTER, x); 101d4d45553Srezgarshakeri CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), 102d4d45553Srezgarshakeri CEED_USE_POINTER, y); 103e83e87a5Sjeremylt 104e83e87a5Sjeremylt // Apply libCEED operator 105d4d45553Srezgarshakeri CeedOperatorApply(op_apply_ctx->op, op_apply_ctx->x_ceed, op_apply_ctx->y_ceed, 106d4d45553Srezgarshakeri CEED_REQUEST_IMMEDIATE); 107e83e87a5Sjeremylt 108e83e87a5Sjeremylt // Restore PETSc vectors 109d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), NULL); 110d4d45553Srezgarshakeri CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), NULL); 111d4d45553Srezgarshakeri ierr = VecRestoreArrayReadAndMemType(op_apply_ctx->X_loc, 112d4d45553Srezgarshakeri (const PetscScalar **)&x); 113e83e87a5Sjeremylt CHKERRQ(ierr); 114d4d45553Srezgarshakeri ierr = VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y); CHKERRQ(ierr); 115e83e87a5Sjeremylt 116e83e87a5Sjeremylt // Local-to-global 117e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 118d4d45553Srezgarshakeri ierr = DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, Y); 119d4d45553Srezgarshakeri CHKERRQ(ierr); 120e83e87a5Sjeremylt 121e83e87a5Sjeremylt PetscFunctionReturn(0); 122e83e87a5Sjeremylt }; 123e83e87a5Sjeremylt 124e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 125e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell 126e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 127e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 128e83e87a5Sjeremylt PetscErrorCode ierr; 129d4d45553Srezgarshakeri OperatorApplyContext op_apply_ctx; 130e83e87a5Sjeremylt 131e83e87a5Sjeremylt PetscFunctionBeginUser; 132e83e87a5Sjeremylt 133d4d45553Srezgarshakeri ierr = MatShellGetContext(A, &op_apply_ctx); CHKERRQ(ierr); 134e83e87a5Sjeremylt 135e83e87a5Sjeremylt // libCEED for local action of residual evaluator 136d4d45553Srezgarshakeri ierr = ApplyLocal_Ceed(X, Y, op_apply_ctx); CHKERRQ(ierr); 137e83e87a5Sjeremylt 138e83e87a5Sjeremylt PetscFunctionReturn(0); 139e83e87a5Sjeremylt }; 140e83e87a5Sjeremylt 141e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 142e83e87a5Sjeremylt // This function wraps the libCEED operator for a SNES residual evaluation 143e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 144e83e87a5Sjeremylt PetscErrorCode FormResidual_Ceed(SNES snes, Vec X, Vec Y, void *ctx) { 145e83e87a5Sjeremylt PetscErrorCode ierr; 146d4d45553Srezgarshakeri OperatorApplyContext op_apply_ctx = (OperatorApplyContext)ctx; 147e83e87a5Sjeremylt 148e83e87a5Sjeremylt PetscFunctionBeginUser; 149e83e87a5Sjeremylt 150e83e87a5Sjeremylt // libCEED for local action of residual evaluator 151d4d45553Srezgarshakeri ierr = ApplyLocal_Ceed(X, Y, op_apply_ctx); CHKERRQ(ierr); 152e83e87a5Sjeremylt 153e83e87a5Sjeremylt PetscFunctionReturn(0); 154e83e87a5Sjeremylt }; 155e83e87a5Sjeremylt 156e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 157e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator 158e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 159e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) { 160e83e87a5Sjeremylt PetscErrorCode ierr; 161d4d45553Srezgarshakeri ProlongRestrContext pr_restr_ctx; 162e83e87a5Sjeremylt PetscScalar *c, *f; 1639b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 164e83e87a5Sjeremylt 165e83e87a5Sjeremylt PetscFunctionBeginUser; 166e83e87a5Sjeremylt 167d4d45553Srezgarshakeri ierr = MatShellGetContext(A, &pr_restr_ctx); CHKERRQ(ierr); 168e83e87a5Sjeremylt 169e83e87a5Sjeremylt // Global-to-local 170d4d45553Srezgarshakeri ierr = VecZeroEntries(pr_restr_ctx->loc_vec_c); CHKERRQ(ierr); 171d4d45553Srezgarshakeri ierr = DMGlobalToLocal(pr_restr_ctx->dmc, X, INSERT_VALUES, 172d4d45553Srezgarshakeri pr_restr_ctx->loc_vec_c); 173e83e87a5Sjeremylt CHKERRQ(ierr); 174e83e87a5Sjeremylt 175e83e87a5Sjeremylt // Setup libCEED vectors 176d4d45553Srezgarshakeri ierr = VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_c, 177d4d45553Srezgarshakeri (const PetscScalar **)&c, 1789b072555Sjeremylt &c_mem_type); CHKERRQ(ierr); 179d4d45553Srezgarshakeri ierr = VecGetArrayAndMemType(pr_restr_ctx->loc_vec_f, &f, &f_mem_type); 180d4d45553Srezgarshakeri CHKERRQ(ierr); 181d4d45553Srezgarshakeri CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), 182d4d45553Srezgarshakeri CEED_USE_POINTER, c); 183d4d45553Srezgarshakeri CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), 184d4d45553Srezgarshakeri CEED_USE_POINTER, f); 185e83e87a5Sjeremylt 186e83e87a5Sjeremylt // Apply libCEED operator 187d4d45553Srezgarshakeri CeedOperatorApply(pr_restr_ctx->op_prolong, pr_restr_ctx->ceed_vec_c, 188d4d45553Srezgarshakeri pr_restr_ctx->ceed_vec_f, CEED_REQUEST_IMMEDIATE); 189e83e87a5Sjeremylt 190e83e87a5Sjeremylt // Restore PETSc vectors 191d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 192d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 193d4d45553Srezgarshakeri ierr = VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_c, 194d4d45553Srezgarshakeri (const PetscScalar **)&c); 195e83e87a5Sjeremylt CHKERRQ(ierr); 196d4d45553Srezgarshakeri ierr = VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_f, &f); CHKERRQ(ierr); 197e83e87a5Sjeremylt 198e83e87a5Sjeremylt // Multiplicity 199d4d45553Srezgarshakeri ierr = VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, 200d4d45553Srezgarshakeri pr_restr_ctx->mult_vec); 201e83e87a5Sjeremylt 202e83e87a5Sjeremylt // Local-to-global 203e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 204d4d45553Srezgarshakeri ierr = DMLocalToGlobal(pr_restr_ctx->dmf, pr_restr_ctx->loc_vec_f, ADD_VALUES, 205d4d45553Srezgarshakeri Y); CHKERRQ(ierr); 206e83e87a5Sjeremylt 207e83e87a5Sjeremylt PetscFunctionReturn(0); 208e83e87a5Sjeremylt }; 209e83e87a5Sjeremylt 210e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 211e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator 212e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 213e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) { 214e83e87a5Sjeremylt PetscErrorCode ierr; 215d4d45553Srezgarshakeri ProlongRestrContext pr_restr_ctx; 216e83e87a5Sjeremylt PetscScalar *c, *f; 2179b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 218e83e87a5Sjeremylt 219e83e87a5Sjeremylt PetscFunctionBeginUser; 220e83e87a5Sjeremylt 221d4d45553Srezgarshakeri ierr = MatShellGetContext(A, &pr_restr_ctx); CHKERRQ(ierr); 222e83e87a5Sjeremylt 223e83e87a5Sjeremylt // Global-to-local 224d4d45553Srezgarshakeri ierr = VecZeroEntries(pr_restr_ctx->loc_vec_f); CHKERRQ(ierr); 225d4d45553Srezgarshakeri ierr = DMGlobalToLocal(pr_restr_ctx->dmf, X, INSERT_VALUES, 226d4d45553Srezgarshakeri pr_restr_ctx->loc_vec_f); 227e83e87a5Sjeremylt CHKERRQ(ierr); 228e83e87a5Sjeremylt 229e83e87a5Sjeremylt // Multiplicity 230d4d45553Srezgarshakeri ierr = VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, 231d4d45553Srezgarshakeri pr_restr_ctx->mult_vec); 232e83e87a5Sjeremylt CHKERRQ(ierr); 233e83e87a5Sjeremylt 234e83e87a5Sjeremylt // Setup libCEED vectors 235d4d45553Srezgarshakeri ierr = VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_f, 236d4d45553Srezgarshakeri (const PetscScalar **)&f, 2379b072555Sjeremylt &f_mem_type); CHKERRQ(ierr); 238d4d45553Srezgarshakeri ierr = VecGetArrayAndMemType(pr_restr_ctx->loc_vec_c, &c, &c_mem_type); 239d4d45553Srezgarshakeri CHKERRQ(ierr); 240d4d45553Srezgarshakeri CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), 241d4d45553Srezgarshakeri CEED_USE_POINTER, f); 242d4d45553Srezgarshakeri CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), 243d4d45553Srezgarshakeri CEED_USE_POINTER, c); 244e83e87a5Sjeremylt 245e83e87a5Sjeremylt // Apply CEED operator 246d4d45553Srezgarshakeri CeedOperatorApply(pr_restr_ctx->op_restrict, pr_restr_ctx->ceed_vec_f, 247d4d45553Srezgarshakeri pr_restr_ctx->ceed_vec_c, CEED_REQUEST_IMMEDIATE); 248e83e87a5Sjeremylt 249e83e87a5Sjeremylt // Restore PETSc vectors 250d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 251d4d45553Srezgarshakeri CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 252d4d45553Srezgarshakeri ierr = VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_f, 253d4d45553Srezgarshakeri (const PetscScalar **)&f); CHKERRQ(ierr); 254d4d45553Srezgarshakeri ierr = VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_c, &c); CHKERRQ(ierr); 255e83e87a5Sjeremylt 256e83e87a5Sjeremylt // Local-to-global 257e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 258d4d45553Srezgarshakeri ierr = DMLocalToGlobal(pr_restr_ctx->dmc, pr_restr_ctx->loc_vec_c, ADD_VALUES, 259d4d45553Srezgarshakeri Y); 260e83e87a5Sjeremylt CHKERRQ(ierr); 261e83e87a5Sjeremylt 262e83e87a5Sjeremylt PetscFunctionReturn(0); 263e83e87a5Sjeremylt }; 264e83e87a5Sjeremylt 265e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 266e83e87a5Sjeremylt // This function calculates the error in the final solution 267e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 268*38f32c05Srezgarshakeri PetscErrorCode ComputeL2Error(Vec X, PetscScalar *l2_error, 269*38f32c05Srezgarshakeri OperatorApplyContext op_error_ctx) { 270e83e87a5Sjeremylt 271*38f32c05Srezgarshakeri Vec E; 272e83e87a5Sjeremylt PetscFunctionBeginUser; 273*38f32c05Srezgarshakeri PetscCall(VecDuplicate(X, &E)); 274*38f32c05Srezgarshakeri PetscCall(ApplyLocal_Ceed(X, E, op_error_ctx) ); 275*38f32c05Srezgarshakeri PetscScalar error_sq = 1.0; 276*38f32c05Srezgarshakeri PetscCall(VecSum(E, &error_sq)); 277*38f32c05Srezgarshakeri *l2_error = sqrt(error_sq); 278e83e87a5Sjeremylt 279e83e87a5Sjeremylt PetscFunctionReturn(0); 280e83e87a5Sjeremylt }; 281e83e87a5Sjeremylt 282e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 283