158600ac3SJames Wright /// @file 240d80af1SJames Wright /// MatCEED implementation 358600ac3SJames Wright 458600ac3SJames Wright #include <ceed.h> 558600ac3SJames Wright #include <ceed/backend.h> 658600ac3SJames Wright #include <mat-ceed-impl.h> 758600ac3SJames Wright #include <mat-ceed.h> 840d80af1SJames Wright #include <petsc-ceed-utils.h> 940d80af1SJames Wright #include <petsc-ceed.h> 1058600ac3SJames Wright #include <petscdmplex.h> 1158600ac3SJames Wright #include <stdlib.h> 1258600ac3SJames Wright #include <string.h> 1358600ac3SJames Wright 1458600ac3SJames Wright PetscClassId MATCEED_CLASSID; 15*c63b910fSJames Wright PetscLogEvent MATCEED_MULT, MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE, MATCEED_MULT_TRANSPOSE_CEEDOP, MATCEED_ASSEMBLE_DIAGONAL, 16*c63b910fSJames Wright MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, MATCEED_SETUP_PBDIAGONAL, MATCEED_SETUP_PBDIAGONAL_CEEDOP, MATCEED_ASSEMBLE_PBDIAGONAL, 17*c63b910fSJames Wright MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, MATCEED_SETUP_FULL, MATCEED_SETUP_FULL_CEEDOP, MATCEED_ASSEMBLE_FULL, MATCEED_ASSEMBLE_FULL_CEEDOP; 1858600ac3SJames Wright 1958600ac3SJames Wright /** 2058600ac3SJames Wright @brief Register MATCEED log events. 2158600ac3SJames Wright 2258600ac3SJames Wright Not collective across MPI processes. 2358600ac3SJames Wright 2458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 2558600ac3SJames Wright **/ 2658600ac3SJames Wright static PetscErrorCode MatCeedRegisterLogEvents() { 2740d80af1SJames Wright static PetscBool registered = PETSC_FALSE; 2858600ac3SJames Wright 2958600ac3SJames Wright PetscFunctionBeginUser; 3058600ac3SJames Wright if (registered) PetscFunctionReturn(PETSC_SUCCESS); 31*c63b910fSJames Wright PetscCall(PetscClassIdRegister("MatCEED", &MATCEED_CLASSID)); 32*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMul", MATCEED_CLASSID, &MATCEED_MULT)); 33*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulCeed", MATCEED_CLASSID, &MATCEED_MULT_CEEDOP)); 34*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulT", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE)); 35*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulTCeed", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE_CEEDOP)); 36*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmDiag", MATCEED_CLASSID, &MATCEED_ASSEMBLE_DIAGONAL)); 37*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSU", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL)); 38*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL_CEEDOP)); 39*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBD", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL)); 40*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP)); 41*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSU", MATCEED_CLASSID, &MATCEED_SETUP_FULL)); 42*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_FULL_CEEDOP)); 43*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsm", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL)); 44*c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL_CEEDOP)); 4540d80af1SJames Wright registered = PETSC_TRUE; 4658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 4758600ac3SJames Wright } 4858600ac3SJames Wright 4958600ac3SJames Wright /** 5058600ac3SJames Wright @brief Assemble the point block diagonal of a `MATCEED` into a `MATAIJ` or similar. 5158600ac3SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 5258600ac3SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 5358600ac3SJames Wright 5458600ac3SJames Wright Collective across MPI processes. 5558600ac3SJames Wright 5658600ac3SJames Wright @param[in] mat_ceed `MATCEED` to assemble 5758600ac3SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 5858600ac3SJames Wright 5958600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 6058600ac3SJames Wright **/ 6158600ac3SJames Wright static PetscErrorCode MatCeedAssemblePointBlockDiagonalCOO(Mat mat_ceed, Mat mat_coo) { 6258600ac3SJames Wright MatCeedContext ctx; 6358600ac3SJames Wright 6458600ac3SJames Wright PetscFunctionBeginUser; 6558600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 6658600ac3SJames Wright 6758600ac3SJames Wright // Check if COO pattern set 6858600ac3SJames Wright { 6958600ac3SJames Wright PetscInt index = -1; 7058600ac3SJames Wright 7158600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 7258600ac3SJames Wright if (ctx->mats_assembled_pbd[i] == mat_coo) index = i; 7358600ac3SJames Wright } 7458600ac3SJames Wright if (index == -1) { 7558600ac3SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 7658600ac3SJames Wright CeedInt *rows_ceed, *cols_ceed; 7758600ac3SJames Wright PetscCount num_entries; 7858600ac3SJames Wright PetscLogStage stage_amg_setup; 7958600ac3SJames Wright 8058600ac3SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 81*c63b910fSJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 8258600ac3SJames Wright if (stage_amg_setup == -1) { 83*c63b910fSJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 8458600ac3SJames Wright } 8558600ac3SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 86*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 87*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 8850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonalSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 89*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 90a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 91a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 9258600ac3SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 9358600ac3SJames Wright free(rows_petsc); 9458600ac3SJames Wright free(cols_petsc); 9550f50432SJames Wright if (!ctx->coo_values_pbd) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_pbd)); 9658600ac3SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_pbd * sizeof(Mat), &ctx->mats_assembled_pbd)); 9758600ac3SJames Wright ctx->mats_assembled_pbd[ctx->num_mats_assembled_pbd - 1] = mat_coo; 98*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 9958600ac3SJames Wright PetscCall(PetscLogStagePop()); 10058600ac3SJames Wright } 10158600ac3SJames Wright } 10258600ac3SJames Wright 10358600ac3SJames Wright // Assemble mat_ceed 104*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 10558600ac3SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 10658600ac3SJames Wright { 10758600ac3SJames Wright const CeedScalar *values; 10858600ac3SJames Wright MatType mat_type; 10958600ac3SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 11058600ac3SJames Wright PetscBool is_spd, is_spd_known; 11158600ac3SJames Wright 11258600ac3SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 11358600ac3SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 11458600ac3SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 11558600ac3SJames Wright else mem_type = CEED_MEM_HOST; 11658600ac3SJames Wright 117*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 11850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonal(ctx->op_mult, ctx->coo_values_pbd, CEED_REQUEST_IMMEDIATE)); 119*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 12050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_pbd, mem_type, &values)); 12158600ac3SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 12258600ac3SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 12358600ac3SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 12450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_pbd, &values)); 12558600ac3SJames Wright } 12658600ac3SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 127*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 12858600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 12958600ac3SJames Wright } 13058600ac3SJames Wright 13158600ac3SJames Wright /** 13258600ac3SJames Wright @brief Assemble inner `Mat` for diagonal `PC` operations 13358600ac3SJames Wright 13458600ac3SJames Wright Collective across MPI processes. 13558600ac3SJames Wright 13658600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 13758600ac3SJames Wright @param[in] use_ceed_pbd Boolean flag to use libCEED PBD assembly 13858600ac3SJames Wright @param[out] mat_inner Inner `Mat` for diagonal operations 13958600ac3SJames Wright 14058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 14158600ac3SJames Wright **/ 14258600ac3SJames Wright static PetscErrorCode MatCeedAssembleInnerBlockDiagonalMat(Mat mat_ceed, PetscBool use_ceed_pbd, Mat *mat_inner) { 14358600ac3SJames Wright MatCeedContext ctx; 14458600ac3SJames Wright 14558600ac3SJames Wright PetscFunctionBeginUser; 14658600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 14758600ac3SJames Wright if (use_ceed_pbd) { 14858600ac3SJames Wright // Check if COO pattern set 14940d80af1SJames Wright if (!ctx->mat_assembled_pbd_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_pbd_internal)); 15058600ac3SJames Wright 15158600ac3SJames Wright // Assemble mat_assembled_full_internal 15258600ac3SJames Wright PetscCall(MatCeedAssemblePointBlockDiagonalCOO(mat_ceed, ctx->mat_assembled_pbd_internal)); 15358600ac3SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_pbd_internal; 15458600ac3SJames Wright } else { 15558600ac3SJames Wright // Check if COO pattern set 15640d80af1SJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 15758600ac3SJames Wright 15858600ac3SJames Wright // Assemble mat_assembled_full_internal 15958600ac3SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 16058600ac3SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_full_internal; 16158600ac3SJames Wright } 16258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 16358600ac3SJames Wright } 16458600ac3SJames Wright 16558600ac3SJames Wright /** 16658600ac3SJames Wright @brief Get `MATCEED` diagonal block for Jacobi. 16758600ac3SJames Wright 16858600ac3SJames Wright Collective across MPI processes. 16958600ac3SJames Wright 17058600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 17158600ac3SJames Wright @param[out] mat_block The diagonal block matrix 17258600ac3SJames Wright 17358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 17458600ac3SJames Wright **/ 17558600ac3SJames Wright static PetscErrorCode MatGetDiagonalBlock_Ceed(Mat mat_ceed, Mat *mat_block) { 17658600ac3SJames Wright Mat mat_inner = NULL; 17758600ac3SJames Wright MatCeedContext ctx; 17858600ac3SJames Wright 17958600ac3SJames Wright PetscFunctionBeginUser; 18058600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 18158600ac3SJames Wright 18258600ac3SJames Wright // Assemble inner mat if needed 18358600ac3SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_pbd_valid, &mat_inner)); 18458600ac3SJames Wright 18558600ac3SJames Wright // Get block diagonal 18658600ac3SJames Wright PetscCall(MatGetDiagonalBlock(mat_inner, mat_block)); 18758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 18858600ac3SJames Wright } 18958600ac3SJames Wright 19058600ac3SJames Wright /** 19158600ac3SJames Wright @brief Invert `MATCEED` diagonal block for Jacobi. 19258600ac3SJames Wright 19358600ac3SJames Wright Collective across MPI processes. 19458600ac3SJames Wright 19558600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 19658600ac3SJames Wright @param[out] values The block inverses in column major order 19758600ac3SJames Wright 19858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 19958600ac3SJames Wright **/ 20058600ac3SJames Wright static PetscErrorCode MatInvertBlockDiagonal_Ceed(Mat mat_ceed, const PetscScalar **values) { 20158600ac3SJames Wright Mat mat_inner = NULL; 20258600ac3SJames Wright MatCeedContext ctx; 20358600ac3SJames Wright 20458600ac3SJames Wright PetscFunctionBeginUser; 20558600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 20658600ac3SJames Wright 20758600ac3SJames Wright // Assemble inner mat if needed 20858600ac3SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_pbd_valid, &mat_inner)); 20958600ac3SJames Wright 21058600ac3SJames Wright // Invert PB diagonal 21158600ac3SJames Wright PetscCall(MatInvertBlockDiagonal(mat_inner, values)); 21258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 21358600ac3SJames Wright } 21458600ac3SJames Wright 21558600ac3SJames Wright /** 21658600ac3SJames Wright @brief Invert `MATCEED` variable diagonal block for Jacobi. 21758600ac3SJames Wright 21858600ac3SJames Wright Collective across MPI processes. 21958600ac3SJames Wright 22058600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 22158600ac3SJames Wright @param[in] num_blocks The number of blocks on the process 22258600ac3SJames Wright @param[in] block_sizes The size of each block on the process 22358600ac3SJames Wright @param[out] values The block inverses in column major order 22458600ac3SJames Wright 22558600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 22658600ac3SJames Wright **/ 22758600ac3SJames Wright static PetscErrorCode MatInvertVariableBlockDiagonal_Ceed(Mat mat_ceed, PetscInt num_blocks, const PetscInt *block_sizes, PetscScalar *values) { 22858600ac3SJames Wright Mat mat_inner = NULL; 22958600ac3SJames Wright MatCeedContext ctx; 23058600ac3SJames Wright 23158600ac3SJames Wright PetscFunctionBeginUser; 23258600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 23358600ac3SJames Wright 23458600ac3SJames Wright // Assemble inner mat if needed 23558600ac3SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_vpbd_valid, &mat_inner)); 23658600ac3SJames Wright 23758600ac3SJames Wright // Invert PB diagonal 23858600ac3SJames Wright PetscCall(MatInvertVariableBlockDiagonal(mat_inner, num_blocks, block_sizes, values)); 23958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 24058600ac3SJames Wright } 24158600ac3SJames Wright 242e90c2ceeSJames Wright /** 243e90c2ceeSJames Wright @brief View `MATCEED`. 244e90c2ceeSJames Wright 245e90c2ceeSJames Wright Collective across MPI processes. 246e90c2ceeSJames Wright 247e90c2ceeSJames Wright @param[in] mat_ceed `MATCEED` to view 248e90c2ceeSJames Wright @param[in] viewer The visualization context 249e90c2ceeSJames Wright 250e90c2ceeSJames Wright @return An error code: 0 - success, otherwise - failure 251e90c2ceeSJames Wright **/ 252e90c2ceeSJames Wright static PetscErrorCode MatView_Ceed(Mat mat_ceed, PetscViewer viewer) { 253e90c2ceeSJames Wright PetscBool is_ascii; 254e90c2ceeSJames Wright PetscViewerFormat format; 255e90c2ceeSJames Wright PetscMPIInt size; 256e90c2ceeSJames Wright MatCeedContext ctx; 257e90c2ceeSJames Wright 258e90c2ceeSJames Wright PetscFunctionBeginUser; 259e90c2ceeSJames Wright PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 260e90c2ceeSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 261e90c2ceeSJames Wright if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat_ceed), &viewer)); 262e90c2ceeSJames Wright 263e90c2ceeSJames Wright PetscCall(PetscViewerGetFormat(viewer, &format)); 264e90c2ceeSJames Wright PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat_ceed), &size)); 265e90c2ceeSJames Wright if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 266e90c2ceeSJames Wright 267e90c2ceeSJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii)); 268e90c2ceeSJames Wright { 269e90c2ceeSJames Wright FILE *file; 270e90c2ceeSJames Wright 27140d80af1SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "MatCEED:\n Default COO MatType:%s\n", ctx->coo_mat_type)); 272e90c2ceeSJames Wright PetscCall(PetscViewerASCIIGetPointer(viewer, &file)); 273e90c2ceeSJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " libCEED Operator:\n")); 274e90c2ceeSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult, file)); 275e90c2ceeSJames Wright if (ctx->op_mult_transpose) { 276e90c2ceeSJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " libCEED Transpose Operator:\n")); 277e90c2ceeSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult_transpose, file)); 278e90c2ceeSJames Wright } 279e90c2ceeSJames Wright } 280e90c2ceeSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 281e90c2ceeSJames Wright } 282e90c2ceeSJames Wright 28358600ac3SJames Wright // ----------------------------------------------------------------------------- 28458600ac3SJames Wright // MatCeed 28558600ac3SJames Wright // ----------------------------------------------------------------------------- 28658600ac3SJames Wright 28758600ac3SJames Wright /** 28858600ac3SJames Wright @brief Create PETSc `Mat` from libCEED operators. 28958600ac3SJames Wright 29058600ac3SJames Wright Collective across MPI processes. 29158600ac3SJames Wright 29258600ac3SJames Wright @param[in] dm_x Input `DM` 29358600ac3SJames Wright @param[in] dm_y Output `DM` 29458600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 29558600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 29658600ac3SJames Wright @param[out] mat New MatCeed 29758600ac3SJames Wright 29858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 29958600ac3SJames Wright **/ 30058600ac3SJames Wright PetscErrorCode MatCeedCreate(DM dm_x, DM dm_y, CeedOperator op_mult, CeedOperator op_mult_transpose, Mat *mat) { 30158600ac3SJames Wright PetscInt X_l_size, X_g_size, Y_l_size, Y_g_size; 30258600ac3SJames Wright VecType vec_type; 30358600ac3SJames Wright MatCeedContext ctx; 30458600ac3SJames Wright 30558600ac3SJames Wright PetscFunctionBeginUser; 30658600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 30758600ac3SJames Wright 30858600ac3SJames Wright // Collect context data 30958600ac3SJames Wright PetscCall(DMGetVecType(dm_x, &vec_type)); 31058600ac3SJames Wright { 31158600ac3SJames Wright Vec X; 31258600ac3SJames Wright 31358600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_x, &X)); 31458600ac3SJames Wright PetscCall(VecGetSize(X, &X_g_size)); 31558600ac3SJames Wright PetscCall(VecGetLocalSize(X, &X_l_size)); 31658600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_x, &X)); 31758600ac3SJames Wright } 31858600ac3SJames Wright if (dm_y) { 31958600ac3SJames Wright Vec Y; 32058600ac3SJames Wright 32158600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_y, &Y)); 32258600ac3SJames Wright PetscCall(VecGetSize(Y, &Y_g_size)); 32358600ac3SJames Wright PetscCall(VecGetLocalSize(Y, &Y_l_size)); 32458600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_y, &Y)); 32558600ac3SJames Wright } else { 32658600ac3SJames Wright dm_y = dm_x; 32758600ac3SJames Wright Y_g_size = X_g_size; 32858600ac3SJames Wright Y_l_size = X_l_size; 32958600ac3SJames Wright } 33040d80af1SJames Wright 33158600ac3SJames Wright // Create context 33258600ac3SJames Wright { 33358600ac3SJames Wright Vec X_loc, Y_loc_transpose = NULL; 33458600ac3SJames Wright 33558600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_x, &X_loc)); 33658600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 33758600ac3SJames Wright if (op_mult_transpose) { 33858600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_y, &Y_loc_transpose)); 33958600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc_transpose)); 34058600ac3SJames Wright } 341*c63b910fSJames Wright PetscCall(MatCeedContextCreate(dm_x, dm_y, X_loc, Y_loc_transpose, op_mult, op_mult_transpose, MATCEED_MULT, MATCEED_MULT_TRANSPOSE, 342*c63b910fSJames Wright MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE_CEEDOP, &ctx)); 34358600ac3SJames Wright PetscCall(VecDestroy(&X_loc)); 34458600ac3SJames Wright PetscCall(VecDestroy(&Y_loc_transpose)); 34558600ac3SJames Wright } 34658600ac3SJames Wright 34758600ac3SJames Wright // Create mat 34858600ac3SJames Wright PetscCall(MatCreateShell(PetscObjectComm((PetscObject)dm_x), Y_l_size, X_l_size, Y_g_size, X_g_size, ctx, mat)); 34958600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)*mat, MATCEED)); 35058600ac3SJames Wright // -- Set block and variable block sizes 35158600ac3SJames Wright if (dm_x == dm_y) { 35258600ac3SJames Wright MatType dm_mat_type, dm_mat_type_copy; 35358600ac3SJames Wright Mat temp_mat; 35458600ac3SJames Wright 35558600ac3SJames Wright PetscCall(DMGetMatType(dm_x, &dm_mat_type)); 35658600ac3SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 35758600ac3SJames Wright PetscCall(DMSetMatType(dm_x, MATAIJ)); 35858600ac3SJames Wright PetscCall(DMCreateMatrix(dm_x, &temp_mat)); 35958600ac3SJames Wright PetscCall(DMSetMatType(dm_x, dm_mat_type_copy)); 36058600ac3SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 36158600ac3SJames Wright 36258600ac3SJames Wright { 36358600ac3SJames Wright PetscInt block_size, num_blocks, max_vblock_size = PETSC_INT_MAX; 36458600ac3SJames Wright const PetscInt *vblock_sizes; 36558600ac3SJames Wright 36658600ac3SJames Wright // -- Get block sizes 36758600ac3SJames Wright PetscCall(MatGetBlockSize(temp_mat, &block_size)); 36858600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(temp_mat, &num_blocks, &vblock_sizes)); 36958600ac3SJames Wright { 37058600ac3SJames Wright PetscInt local_min_max[2] = {0}, global_min_max[2] = {0, PETSC_INT_MAX}; 37158600ac3SJames Wright 37258600ac3SJames Wright for (PetscInt i = 0; i < num_blocks; i++) local_min_max[1] = PetscMax(local_min_max[1], vblock_sizes[i]); 37358600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_min_max, global_min_max)); 37458600ac3SJames Wright max_vblock_size = global_min_max[1]; 37558600ac3SJames Wright } 37658600ac3SJames Wright 37758600ac3SJames Wright // -- Copy block sizes 37858600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(*mat, block_size)); 37958600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(*mat, num_blocks, (PetscInt *)vblock_sizes)); 38058600ac3SJames Wright 38158600ac3SJames Wright // -- Check libCEED compatibility 38258600ac3SJames Wright { 38358600ac3SJames Wright bool is_composite; 38458600ac3SJames Wright 38558600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_TRUE; 38658600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_TRUE; 38750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorIsComposite(op_mult, &is_composite)); 38858600ac3SJames Wright if (is_composite) { 38958600ac3SJames Wright CeedInt num_sub_operators; 39058600ac3SJames Wright CeedOperator *sub_operators; 39158600ac3SJames Wright 39250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetNumSub(op_mult, &num_sub_operators)); 39350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetSubList(op_mult, &sub_operators)); 39458600ac3SJames Wright for (CeedInt i = 0; i < num_sub_operators; i++) { 39558600ac3SJames Wright CeedInt num_bases, num_comp; 39658600ac3SJames Wright CeedBasis *active_bases; 39758600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 39858600ac3SJames Wright 39950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(sub_operators[i], &assembly_data)); 40050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 40150f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 40258600ac3SJames Wright if (num_bases > 1) { 40358600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 40458600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 40558600ac3SJames Wright } 40658600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 40758600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 40858600ac3SJames Wright } 40958600ac3SJames Wright } else { 41058600ac3SJames Wright // LCOV_EXCL_START 41158600ac3SJames Wright CeedInt num_bases, num_comp; 41258600ac3SJames Wright CeedBasis *active_bases; 41358600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 41458600ac3SJames Wright 41550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(op_mult, &assembly_data)); 41650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 41750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 41858600ac3SJames Wright if (num_bases > 1) { 41958600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 42058600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 42158600ac3SJames Wright } 42258600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 42358600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 42458600ac3SJames Wright // LCOV_EXCL_STOP 42558600ac3SJames Wright } 42658600ac3SJames Wright { 42758600ac3SJames Wright PetscInt local_is_valid[2], global_is_valid[2]; 42858600ac3SJames Wright 42958600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_pbd_valid; 43058600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 43158600ac3SJames Wright ctx->is_ceed_pbd_valid = global_is_valid[0]; 43258600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_vpbd_valid; 43358600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 43458600ac3SJames Wright ctx->is_ceed_vpbd_valid = global_is_valid[0]; 43558600ac3SJames Wright } 43658600ac3SJames Wright } 43758600ac3SJames Wright } 43858600ac3SJames Wright PetscCall(MatDestroy(&temp_mat)); 43958600ac3SJames Wright } 44058600ac3SJames Wright // -- Set internal mat type 44158600ac3SJames Wright { 44258600ac3SJames Wright VecType vec_type; 44340d80af1SJames Wright MatType coo_mat_type; 44458600ac3SJames Wright 44558600ac3SJames Wright PetscCall(VecGetType(ctx->X_loc, &vec_type)); 44640d80af1SJames Wright if (strstr(vec_type, VECCUDA)) coo_mat_type = MATAIJCUSPARSE; 44740d80af1SJames Wright else if (strstr(vec_type, VECKOKKOS)) coo_mat_type = MATAIJKOKKOS; 44840d80af1SJames Wright else coo_mat_type = MATAIJ; 44940d80af1SJames Wright PetscCall(PetscStrallocpy(coo_mat_type, &ctx->coo_mat_type)); 45058600ac3SJames Wright } 45158600ac3SJames Wright // -- Set mat operations 45258600ac3SJames Wright PetscCall(MatShellSetContextDestroy(*mat, (PetscErrorCode(*)(void *))MatCeedContextDestroy)); 453e90c2ceeSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 45458600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 45558600ac3SJames Wright if (op_mult_transpose) PetscCall(MatShellSetOperation(*mat, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 45658600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 45758600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 45858600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_INVERT_BLOCK_DIAGONAL, (void (*)(void))MatInvertBlockDiagonal_Ceed)); 45958600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_INVERT_VBLOCK_DIAGONAL, (void (*)(void))MatInvertVariableBlockDiagonal_Ceed)); 46058600ac3SJames Wright PetscCall(MatShellSetVecType(*mat, vec_type)); 46158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 46258600ac3SJames Wright } 46358600ac3SJames Wright 46458600ac3SJames Wright /** 46558600ac3SJames Wright @brief Copy `MATCEED` into a compatible `Mat` with type `MatShell` or `MATCEED`. 46658600ac3SJames Wright 46758600ac3SJames Wright Collective across MPI processes. 46858600ac3SJames Wright 46958600ac3SJames Wright @param[in] mat_ceed `MATCEED` to copy from 47058600ac3SJames Wright @param[out] mat_other `MatShell` or `MATCEED` to copy into 47158600ac3SJames Wright 47258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 47358600ac3SJames Wright **/ 47458600ac3SJames Wright PetscErrorCode MatCeedCopy(Mat mat_ceed, Mat mat_other) { 47558600ac3SJames Wright PetscFunctionBeginUser; 47658600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 47758600ac3SJames Wright 47858600ac3SJames Wright // Check type compatibility 47958600ac3SJames Wright { 48040d80af1SJames Wright PetscBool is_matceed = PETSC_FALSE, is_matshell = PETSC_FALSE; 48158600ac3SJames Wright MatType mat_type_ceed, mat_type_other; 48258600ac3SJames Wright 48358600ac3SJames Wright PetscCall(MatGetType(mat_ceed, &mat_type_ceed)); 48440d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_ceed, MATCEED, &is_matceed)); 48540d80af1SJames Wright PetscCheck(is_matceed, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_ceed must have type " MATCEED); 48640d80af1SJames Wright PetscCall(MatGetType(mat_other, &mat_type_other)); 48740d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_other, MATCEED, &is_matceed)); 48840d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_other, MATSHELL, &is_matceed)); 48940d80af1SJames Wright PetscCheck(is_matceed || is_matshell, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_other must have type " MATCEED " or " MATSHELL); 49058600ac3SJames Wright } 49158600ac3SJames Wright 49258600ac3SJames Wright // Check dimension compatibility 49358600ac3SJames Wright { 49458600ac3SJames Wright PetscInt X_l_ceed_size, X_g_ceed_size, Y_l_ceed_size, Y_g_ceed_size, X_l_other_size, X_g_other_size, Y_l_other_size, Y_g_other_size; 49558600ac3SJames Wright 49658600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_ceed_size, &X_g_ceed_size)); 49758600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_ceed_size, &X_l_ceed_size)); 49858600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_other_size, &X_g_other_size)); 49958600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_other_size, &X_l_other_size)); 50058600ac3SJames Wright PetscCheck((Y_g_ceed_size == Y_g_other_size) && (X_g_ceed_size == X_g_other_size) && (Y_l_ceed_size == Y_l_other_size) && 50158600ac3SJames Wright (X_l_ceed_size == X_l_other_size), 50258600ac3SJames Wright PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, 50358600ac3SJames Wright "mat_ceed and mat_other must have compatible sizes; found mat_ceed (Global: %" PetscInt_FMT ", %" PetscInt_FMT 50458600ac3SJames Wright "; Local: %" PetscInt_FMT ", %" PetscInt_FMT ") mat_other (Global: %" PetscInt_FMT ", %" PetscInt_FMT "; Local: %" PetscInt_FMT 50558600ac3SJames Wright ", %" PetscInt_FMT ")", 50658600ac3SJames Wright Y_g_ceed_size, X_g_ceed_size, Y_l_ceed_size, X_l_ceed_size, Y_g_other_size, X_g_other_size, Y_l_other_size, X_l_other_size); 50758600ac3SJames Wright } 50858600ac3SJames Wright 50958600ac3SJames Wright // Convert 51058600ac3SJames Wright { 51158600ac3SJames Wright VecType vec_type; 51258600ac3SJames Wright MatCeedContext ctx; 51358600ac3SJames Wright 51458600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)mat_other, MATCEED)); 51558600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 51658600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 51758600ac3SJames Wright PetscCall(MatShellSetContext(mat_other, ctx)); 51858600ac3SJames Wright PetscCall(MatShellSetContextDestroy(mat_other, (PetscErrorCode(*)(void *))MatCeedContextDestroy)); 519e90c2ceeSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 52058600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 52158600ac3SJames Wright if (ctx->op_mult_transpose) PetscCall(MatShellSetOperation(mat_other, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 52258600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 52358600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 52458600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_INVERT_BLOCK_DIAGONAL, (void (*)(void))MatInvertBlockDiagonal_Ceed)); 52558600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_INVERT_VBLOCK_DIAGONAL, (void (*)(void))MatInvertVariableBlockDiagonal_Ceed)); 52658600ac3SJames Wright { 52758600ac3SJames Wright PetscInt block_size; 52858600ac3SJames Wright 52958600ac3SJames Wright PetscCall(MatGetBlockSize(mat_ceed, &block_size)); 53058600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(mat_other, block_size)); 53158600ac3SJames Wright } 53258600ac3SJames Wright { 53358600ac3SJames Wright PetscInt num_blocks; 53458600ac3SJames Wright const PetscInt *block_sizes; 53558600ac3SJames Wright 53658600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(mat_ceed, &num_blocks, &block_sizes)); 53758600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(mat_other, num_blocks, (PetscInt *)block_sizes)); 53858600ac3SJames Wright } 53958600ac3SJames Wright PetscCall(DMGetVecType(ctx->dm_x, &vec_type)); 54058600ac3SJames Wright PetscCall(MatShellSetVecType(mat_other, vec_type)); 54158600ac3SJames Wright } 54258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 54358600ac3SJames Wright } 54458600ac3SJames Wright 54558600ac3SJames Wright /** 54640d80af1SJames Wright @brief Setup a `Mat` with the same COO pattern as a `MatCEED`. 54740d80af1SJames Wright 54840d80af1SJames Wright Collective across MPI processes. 54940d80af1SJames Wright 55040d80af1SJames Wright @param[in] mat_ceed `MATCEED` 55140d80af1SJames Wright @param[out] mat_coo Sparse `Mat` with same COO pattern 55240d80af1SJames Wright 55340d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 55440d80af1SJames Wright **/ 55540d80af1SJames Wright PetscErrorCode MatCeedCreateMatCOO(Mat mat_ceed, Mat *mat_coo) { 55640d80af1SJames Wright MatCeedContext ctx; 55740d80af1SJames Wright 55840d80af1SJames Wright PetscFunctionBeginUser; 55940d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 56040d80af1SJames Wright 56140d80af1SJames Wright PetscCheck(ctx->dm_x == ctx->dm_y, PetscObjectComm((PetscObject)mat_ceed), PETSC_ERR_SUP, "COO assembly only supported for MATCEED on a single DM"); 56240d80af1SJames Wright 56340d80af1SJames Wright // Check cl mat type 56440d80af1SJames Wright { 56540d80af1SJames Wright PetscBool is_coo_mat_type_cl = PETSC_FALSE; 56640d80af1SJames Wright char coo_mat_type_cl[64]; 56740d80af1SJames Wright 56840d80af1SJames Wright // Check for specific CL coo mat type for this Mat 56940d80af1SJames Wright { 57040d80af1SJames Wright const char *mat_ceed_prefix = NULL; 57140d80af1SJames Wright 57240d80af1SJames Wright PetscCall(MatGetOptionsPrefix(mat_ceed, &mat_ceed_prefix)); 57340d80af1SJames Wright PetscOptionsBegin(PetscObjectComm((PetscObject)mat_ceed), mat_ceed_prefix, "", NULL); 57440d80af1SJames Wright PetscCall(PetscOptionsFList("-ceed_coo_mat_type", "Default MATCEED COO assembly MatType", NULL, MatList, coo_mat_type_cl, coo_mat_type_cl, 57540d80af1SJames Wright sizeof(coo_mat_type_cl), &is_coo_mat_type_cl)); 57640d80af1SJames Wright PetscOptionsEnd(); 57740d80af1SJames Wright if (is_coo_mat_type_cl) { 57840d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 57940d80af1SJames Wright PetscCall(PetscStrallocpy(coo_mat_type_cl, &ctx->coo_mat_type)); 58040d80af1SJames Wright } 58140d80af1SJames Wright } 58240d80af1SJames Wright } 58340d80af1SJames Wright 58440d80af1SJames Wright // Create sparse matrix 58540d80af1SJames Wright { 58640d80af1SJames Wright MatType dm_mat_type, dm_mat_type_copy; 58740d80af1SJames Wright 58840d80af1SJames Wright PetscCall(DMGetMatType(ctx->dm_x, &dm_mat_type)); 58940d80af1SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 59040d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, ctx->coo_mat_type)); 59140d80af1SJames Wright PetscCall(DMCreateMatrix(ctx->dm_x, mat_coo)); 59240d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, dm_mat_type_copy)); 59340d80af1SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 59440d80af1SJames Wright } 59540d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 59640d80af1SJames Wright } 59740d80af1SJames Wright 59840d80af1SJames Wright /** 59940d80af1SJames Wright @brief Setup the COO preallocation `MATCEED` into a `MATAIJ` or similar. 60058600ac3SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 60158600ac3SJames Wright 60258600ac3SJames Wright Collective across MPI processes. 60358600ac3SJames Wright 60458600ac3SJames Wright @param[in] mat_ceed `MATCEED` to assemble 60558600ac3SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 60658600ac3SJames Wright 60758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 60858600ac3SJames Wright **/ 60940d80af1SJames Wright PetscErrorCode MatCeedSetPreallocationCOO(Mat mat_ceed, Mat mat_coo) { 61058600ac3SJames Wright MatCeedContext ctx; 61158600ac3SJames Wright 61258600ac3SJames Wright PetscFunctionBeginUser; 61358600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 61458600ac3SJames Wright 61558600ac3SJames Wright { 61658600ac3SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 61758600ac3SJames Wright CeedInt *rows_ceed, *cols_ceed; 61858600ac3SJames Wright PetscCount num_entries; 61958600ac3SJames Wright PetscLogStage stage_amg_setup; 62058600ac3SJames Wright 62158600ac3SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 622*c63b910fSJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 62358600ac3SJames Wright if (stage_amg_setup == -1) { 624*c63b910fSJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 62558600ac3SJames Wright } 62658600ac3SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 627*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 628*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 62950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 630*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 631a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 632a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 63358600ac3SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 63458600ac3SJames Wright free(rows_petsc); 63558600ac3SJames Wright free(cols_petsc); 63650f50432SJames Wright if (!ctx->coo_values_full) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_full)); 63758600ac3SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_full * sizeof(Mat), &ctx->mats_assembled_full)); 63858600ac3SJames Wright ctx->mats_assembled_full[ctx->num_mats_assembled_full - 1] = mat_coo; 639*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 64058600ac3SJames Wright PetscCall(PetscLogStagePop()); 64158600ac3SJames Wright } 64240d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 64340d80af1SJames Wright } 64440d80af1SJames Wright 64540d80af1SJames Wright /** 64640d80af1SJames Wright @brief Assemble a `MATCEED` into a `MATAIJ` or similar. 64740d80af1SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 64840d80af1SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 64940d80af1SJames Wright 65040d80af1SJames Wright Collective across MPI processes. 65140d80af1SJames Wright 65240d80af1SJames Wright @param[in] mat_ceed `MATCEED` to assemble 65340d80af1SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 65440d80af1SJames Wright 65540d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 65640d80af1SJames Wright **/ 65740d80af1SJames Wright PetscErrorCode MatCeedAssembleCOO(Mat mat_ceed, Mat mat_coo) { 65840d80af1SJames Wright MatCeedContext ctx; 65940d80af1SJames Wright 66040d80af1SJames Wright PetscFunctionBeginUser; 66140d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 66240d80af1SJames Wright 66340d80af1SJames Wright // Set COO pattern if needed 66440d80af1SJames Wright { 66540d80af1SJames Wright CeedInt index = -1; 66640d80af1SJames Wright 66740d80af1SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 66840d80af1SJames Wright if (ctx->mats_assembled_full[i] == mat_coo) index = i; 66940d80af1SJames Wright } 67040d80af1SJames Wright if (index == -1) PetscCall(MatCeedSetPreallocationCOO(mat_ceed, mat_coo)); 67158600ac3SJames Wright } 67258600ac3SJames Wright 67358600ac3SJames Wright // Assemble mat_ceed 674*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 67558600ac3SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 67658600ac3SJames Wright { 67758600ac3SJames Wright const CeedScalar *values; 67858600ac3SJames Wright MatType mat_type; 67958600ac3SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 68058600ac3SJames Wright PetscBool is_spd, is_spd_known; 68158600ac3SJames Wright 68258600ac3SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 68358600ac3SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 68458600ac3SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 68558600ac3SJames Wright else mem_type = CEED_MEM_HOST; 68658600ac3SJames Wright 687*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 68850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemble(ctx->op_mult, ctx->coo_values_full)); 689*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 69050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_full, mem_type, &values)); 69158600ac3SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 69258600ac3SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 69358600ac3SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 69450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_full, &values)); 69558600ac3SJames Wright } 69658600ac3SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 697*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 69858600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 69958600ac3SJames Wright } 70058600ac3SJames Wright 70158600ac3SJames Wright /** 70240d80af1SJames Wright @brief Set the current value of a context field for a `MatCEED`. 70340d80af1SJames Wright 70440d80af1SJames Wright Not collective across MPI processes. 70540d80af1SJames Wright 70640d80af1SJames Wright @param[in,out] mat `MatCEED` 70740d80af1SJames Wright @param[in] name Name of the context field 70840d80af1SJames Wright @param[in] value New context field value 70940d80af1SJames Wright 71040d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 71140d80af1SJames Wright **/ 71240d80af1SJames Wright PetscErrorCode MatCeedSetContextDouble(Mat mat, const char *name, double value) { 71340d80af1SJames Wright PetscBool was_updated = PETSC_FALSE; 71440d80af1SJames Wright MatCeedContext ctx; 71540d80af1SJames Wright 71640d80af1SJames Wright PetscFunctionBeginUser; 71740d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 71840d80af1SJames Wright { 71940d80af1SJames Wright CeedContextFieldLabel label = NULL; 72040d80af1SJames Wright 72140d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult, name, &label)); 72240d80af1SJames Wright if (label) { 72340d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult, label, &value)); 72440d80af1SJames Wright was_updated = PETSC_TRUE; 72540d80af1SJames Wright } 72640d80af1SJames Wright if (ctx->op_mult_transpose) { 72740d80af1SJames Wright label = NULL; 72840d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult_transpose, name, &label)); 72940d80af1SJames Wright if (label) { 73040d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult_transpose, label, &value)); 73140d80af1SJames Wright was_updated = PETSC_TRUE; 73240d80af1SJames Wright } 73340d80af1SJames Wright } 73440d80af1SJames Wright } 73540d80af1SJames Wright if (was_updated) { 73640d80af1SJames Wright PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 73740d80af1SJames Wright PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 73840d80af1SJames Wright } 73940d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 74040d80af1SJames Wright } 74140d80af1SJames Wright 74240d80af1SJames Wright /** 74351bb547fSJames Wright @brief Set the current `PetscReal` value of a context field for a `MatCEED`. 74451bb547fSJames Wright 74551bb547fSJames Wright Not collective across MPI processes. 74651bb547fSJames Wright 74751bb547fSJames Wright @param[in,out] mat `MatCEED` 74851bb547fSJames Wright @param[in] name Name of the context field 74951bb547fSJames Wright @param[in] value New context field value 75051bb547fSJames Wright 75151bb547fSJames Wright @return An error code: 0 - success, otherwise - failure 75251bb547fSJames Wright **/ 75351bb547fSJames Wright PetscErrorCode MatCeedSetContextReal(Mat mat, const char *name, PetscReal value) { 75451bb547fSJames Wright double value_double = value; 75551bb547fSJames Wright 75651bb547fSJames Wright PetscFunctionBeginUser; 75751bb547fSJames Wright PetscCall(MatCeedSetContextDouble(mat, name, value_double)); 75851bb547fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 75951bb547fSJames Wright } 76051bb547fSJames Wright 76151bb547fSJames Wright /** 76240d80af1SJames Wright @brief Get the current value of a context field for a `MatCEED`. 76340d80af1SJames Wright 76440d80af1SJames Wright Not collective across MPI processes. 76540d80af1SJames Wright 76640d80af1SJames Wright @param[in] mat `MatCEED` 76740d80af1SJames Wright @param[in] name Name of the context field 76840d80af1SJames Wright @param[out] value Current context field value 76940d80af1SJames Wright 77040d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 77140d80af1SJames Wright **/ 77240d80af1SJames Wright PetscErrorCode MatCeedGetContextDouble(Mat mat, const char *name, double *value) { 77340d80af1SJames Wright MatCeedContext ctx; 77440d80af1SJames Wright 77540d80af1SJames Wright PetscFunctionBeginUser; 77640d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 77740d80af1SJames Wright { 77840d80af1SJames Wright CeedContextFieldLabel label = NULL; 77940d80af1SJames Wright CeedOperator op = ctx->op_mult; 78040d80af1SJames Wright 78140d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 78240d80af1SJames Wright if (!label && ctx->op_mult_transpose) { 78340d80af1SJames Wright op = ctx->op_mult_transpose; 78440d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 78540d80af1SJames Wright } 78640d80af1SJames Wright if (label) { 78740d80af1SJames Wright PetscSizeT num_values; 78840d80af1SJames Wright const double *values_ceed; 78940d80af1SJames Wright 79040d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextDoubleRead(op, label, &num_values, &values_ceed)); 79140d80af1SJames Wright *value = values_ceed[0]; 79240d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorRestoreContextDoubleRead(op, label, &values_ceed)); 79340d80af1SJames Wright } 79440d80af1SJames Wright } 79540d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 79640d80af1SJames Wright } 79740d80af1SJames Wright 79840d80af1SJames Wright /** 79951bb547fSJames Wright @brief Get the current `PetscReal` value of a context field for a `MatCEED`. 80051bb547fSJames Wright 80151bb547fSJames Wright Not collective across MPI processes. 80251bb547fSJames Wright 80351bb547fSJames Wright @param[in] mat `MatCEED` 80451bb547fSJames Wright @param[in] name Name of the context field 80551bb547fSJames Wright @param[out] value Current context field value 80651bb547fSJames Wright 80751bb547fSJames Wright @return An error code: 0 - success, otherwise - failure 80851bb547fSJames Wright **/ 80951bb547fSJames Wright PetscErrorCode MatCeedGetContextReal(Mat mat, const char *name, PetscReal *value) { 81051bb547fSJames Wright double value_double; 81151bb547fSJames Wright 81251bb547fSJames Wright PetscFunctionBeginUser; 81351bb547fSJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &value_double)); 81451bb547fSJames Wright *value = value_double; 81551bb547fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 81651bb547fSJames Wright } 81751bb547fSJames Wright 81851bb547fSJames Wright /** 81958600ac3SJames Wright @brief Set user context for a `MATCEED`. 82058600ac3SJames Wright 82158600ac3SJames Wright Collective across MPI processes. 82258600ac3SJames Wright 82358600ac3SJames Wright @param[in,out] mat `MATCEED` 82458600ac3SJames Wright @param[in] f The context destroy function, or NULL 82558600ac3SJames Wright @param[in] ctx User context, or NULL to unset 82658600ac3SJames Wright 82758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 82858600ac3SJames Wright **/ 82958600ac3SJames Wright PetscErrorCode MatCeedSetContext(Mat mat, PetscErrorCode (*f)(void *), void *ctx) { 83058600ac3SJames Wright PetscContainer user_ctx = NULL; 83158600ac3SJames Wright 83258600ac3SJames Wright PetscFunctionBeginUser; 83358600ac3SJames Wright if (ctx) { 83458600ac3SJames Wright PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)mat), &user_ctx)); 83558600ac3SJames Wright PetscCall(PetscContainerSetPointer(user_ctx, ctx)); 83658600ac3SJames Wright PetscCall(PetscContainerSetUserDestroy(user_ctx, f)); 83758600ac3SJames Wright } 83858600ac3SJames Wright PetscCall(PetscObjectCompose((PetscObject)mat, "MatCeed user context", (PetscObject)user_ctx)); 83958600ac3SJames Wright PetscCall(PetscContainerDestroy(&user_ctx)); 84058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 84158600ac3SJames Wright } 84258600ac3SJames Wright 84358600ac3SJames Wright /** 84458600ac3SJames Wright @brief Retrieve the user context for a `MATCEED`. 84558600ac3SJames Wright 84658600ac3SJames Wright Collective across MPI processes. 84758600ac3SJames Wright 84858600ac3SJames Wright @param[in,out] mat `MATCEED` 84958600ac3SJames Wright @param[in] ctx User context 85058600ac3SJames Wright 85158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 85258600ac3SJames Wright **/ 85358600ac3SJames Wright PetscErrorCode MatCeedGetContext(Mat mat, void *ctx) { 85458600ac3SJames Wright PetscContainer user_ctx; 85558600ac3SJames Wright 85658600ac3SJames Wright PetscFunctionBeginUser; 85758600ac3SJames Wright PetscCall(PetscObjectQuery((PetscObject)mat, "MatCeed user context", (PetscObject *)&user_ctx)); 85858600ac3SJames Wright if (user_ctx) PetscCall(PetscContainerGetPointer(user_ctx, (void **)ctx)); 85958600ac3SJames Wright else *(void **)ctx = NULL; 86058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 86158600ac3SJames Wright } 86258600ac3SJames Wright /** 86340d80af1SJames Wright @brief Set a user defined matrix operation for a `MATCEED` matrix. 86440d80af1SJames Wright 86540d80af1SJames Wright Within each user-defined routine, the user should call `MatCeedGetContext()` to obtain the user-defined context that was set by 86640d80af1SJames Wright `MatCeedSetContext()`. 86758600ac3SJames Wright 86858600ac3SJames Wright Collective across MPI processes. 86958600ac3SJames Wright 87058600ac3SJames Wright @param[in,out] mat `MATCEED` 87140d80af1SJames Wright @param[in] op Name of the `MatOperation` 87240d80af1SJames Wright @param[in] g Function that provides the operation 87358600ac3SJames Wright 87458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 87558600ac3SJames Wright **/ 87640d80af1SJames Wright PetscErrorCode MatCeedSetOperation(Mat mat, MatOperation op, void (*g)(void)) { 87740d80af1SJames Wright PetscFunctionBeginUser; 87840d80af1SJames Wright PetscCall(MatShellSetOperation(mat, op, g)); 87940d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 88040d80af1SJames Wright } 88140d80af1SJames Wright 88240d80af1SJames Wright /** 88340d80af1SJames Wright @brief Sets the default COO matrix type as a string from the `MATCEED`. 88440d80af1SJames Wright 88540d80af1SJames Wright Collective across MPI processes. 88640d80af1SJames Wright 88740d80af1SJames Wright @param[in,out] mat `MATCEED` 88840d80af1SJames Wright @param[in] type COO `MatType` to set 88940d80af1SJames Wright 89040d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 89140d80af1SJames Wright **/ 89240d80af1SJames Wright PetscErrorCode MatCeedSetCOOMatType(Mat mat, MatType type) { 89358600ac3SJames Wright MatCeedContext ctx; 89458600ac3SJames Wright 89558600ac3SJames Wright PetscFunctionBeginUser; 89658600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 89758600ac3SJames Wright // Check if same 89858600ac3SJames Wright { 89958600ac3SJames Wright size_t len_old, len_new; 90058600ac3SJames Wright PetscBool is_same = PETSC_FALSE; 90158600ac3SJames Wright 90240d80af1SJames Wright PetscCall(PetscStrlen(ctx->coo_mat_type, &len_old)); 90358600ac3SJames Wright PetscCall(PetscStrlen(type, &len_new)); 90440d80af1SJames Wright if (len_old == len_new) PetscCall(PetscStrncmp(ctx->coo_mat_type, type, len_old, &is_same)); 90558600ac3SJames Wright if (is_same) PetscFunctionReturn(PETSC_SUCCESS); 90658600ac3SJames Wright } 90758600ac3SJames Wright // Clean up old mats in different format 90858600ac3SJames Wright // LCOV_EXCL_START 90958600ac3SJames Wright if (ctx->mat_assembled_full_internal) { 91058600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 91158600ac3SJames Wright if (ctx->mats_assembled_full[i] == ctx->mat_assembled_full_internal) { 91258600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_full; j++) { 91358600ac3SJames Wright ctx->mats_assembled_full[j - 1] = ctx->mats_assembled_full[j]; 91458600ac3SJames Wright } 91558600ac3SJames Wright ctx->num_mats_assembled_full--; 91658600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 91758600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 91858600ac3SJames Wright } 91958600ac3SJames Wright } 92058600ac3SJames Wright } 92158600ac3SJames Wright if (ctx->mat_assembled_pbd_internal) { 92258600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 92358600ac3SJames Wright if (ctx->mats_assembled_pbd[i] == ctx->mat_assembled_pbd_internal) { 92458600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_pbd; j++) { 92558600ac3SJames Wright ctx->mats_assembled_pbd[j - 1] = ctx->mats_assembled_pbd[j]; 92658600ac3SJames Wright } 92758600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 92858600ac3SJames Wright ctx->num_mats_assembled_pbd--; 92958600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 93058600ac3SJames Wright } 93158600ac3SJames Wright } 93258600ac3SJames Wright } 93340d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 93440d80af1SJames Wright PetscCall(PetscStrallocpy(type, &ctx->coo_mat_type)); 93558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 93658600ac3SJames Wright // LCOV_EXCL_STOP 93758600ac3SJames Wright } 93858600ac3SJames Wright 93958600ac3SJames Wright /** 94040d80af1SJames Wright @brief Gets the default COO matrix type as a string from the `MATCEED`. 94158600ac3SJames Wright 94258600ac3SJames Wright Collective across MPI processes. 94358600ac3SJames Wright 94458600ac3SJames Wright @param[in,out] mat `MATCEED` 94540d80af1SJames Wright @param[in] type COO `MatType` 94658600ac3SJames Wright 94758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 94858600ac3SJames Wright **/ 94940d80af1SJames Wright PetscErrorCode MatCeedGetCOOMatType(Mat mat, MatType *type) { 95058600ac3SJames Wright MatCeedContext ctx; 95158600ac3SJames Wright 95258600ac3SJames Wright PetscFunctionBeginUser; 95358600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 95440d80af1SJames Wright *type = ctx->coo_mat_type; 95558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 95658600ac3SJames Wright } 95758600ac3SJames Wright 95858600ac3SJames Wright /** 95958600ac3SJames Wright @brief Set input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 96058600ac3SJames Wright 96158600ac3SJames Wright Not collective across MPI processes. 96258600ac3SJames Wright 96358600ac3SJames Wright @param[in,out] mat `MATCEED` 96458600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 96558600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 96658600ac3SJames Wright 96758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 96858600ac3SJames Wright **/ 96958600ac3SJames Wright PetscErrorCode MatCeedSetLocalVectors(Mat mat, Vec X_loc, Vec Y_loc_transpose) { 97058600ac3SJames Wright MatCeedContext ctx; 97158600ac3SJames Wright 97258600ac3SJames Wright PetscFunctionBeginUser; 97358600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 97458600ac3SJames Wright if (X_loc) { 97558600ac3SJames Wright PetscInt len_old, len_new; 97658600ac3SJames Wright 97758600ac3SJames Wright PetscCall(VecGetSize(ctx->X_loc, &len_old)); 97858600ac3SJames Wright PetscCall(VecGetSize(X_loc, &len_new)); 97958600ac3SJames Wright PetscCheck(len_old == len_new, PETSC_COMM_SELF, PETSC_ERR_LIB, "new X_loc length %" PetscInt_FMT " should match old X_loc length %" PetscInt_FMT, 98058600ac3SJames Wright len_new, len_old); 98140d80af1SJames Wright PetscCall(VecReferenceCopy(X_loc, &ctx->X_loc)); 98258600ac3SJames Wright } 98358600ac3SJames Wright if (Y_loc_transpose) { 98458600ac3SJames Wright PetscInt len_old, len_new; 98558600ac3SJames Wright 98658600ac3SJames Wright PetscCall(VecGetSize(ctx->Y_loc_transpose, &len_old)); 98758600ac3SJames Wright PetscCall(VecGetSize(Y_loc_transpose, &len_new)); 98858600ac3SJames Wright PetscCheck(len_old == len_new, PETSC_COMM_SELF, PETSC_ERR_LIB, 98958600ac3SJames Wright "new Y_loc_transpose length %" PetscInt_FMT " should match old Y_loc_transpose length %" PetscInt_FMT, len_new, len_old); 99040d80af1SJames Wright PetscCall(VecReferenceCopy(Y_loc_transpose, &ctx->Y_loc_transpose)); 99158600ac3SJames Wright } 99258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 99358600ac3SJames Wright } 99458600ac3SJames Wright 99558600ac3SJames Wright /** 99658600ac3SJames Wright @brief Get input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 99758600ac3SJames Wright 99858600ac3SJames Wright Not collective across MPI processes. 99958600ac3SJames Wright 100058600ac3SJames Wright @param[in,out] mat `MATCEED` 100158600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 100258600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 100358600ac3SJames Wright 100458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 100558600ac3SJames Wright **/ 100658600ac3SJames Wright PetscErrorCode MatCeedGetLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 100758600ac3SJames Wright MatCeedContext ctx; 100858600ac3SJames Wright 100958600ac3SJames Wright PetscFunctionBeginUser; 101058600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 101158600ac3SJames Wright if (X_loc) { 101240d80af1SJames Wright *X_loc = NULL; 101340d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->X_loc, X_loc)); 101458600ac3SJames Wright } 101558600ac3SJames Wright if (Y_loc_transpose) { 101640d80af1SJames Wright *Y_loc_transpose = NULL; 101740d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->Y_loc_transpose, Y_loc_transpose)); 101858600ac3SJames Wright } 101958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 102058600ac3SJames Wright } 102158600ac3SJames Wright 102258600ac3SJames Wright /** 102358600ac3SJames Wright @brief Restore input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 102458600ac3SJames Wright 102558600ac3SJames Wright Not collective across MPI processes. 102658600ac3SJames Wright 102758600ac3SJames Wright @param[in,out] mat MatCeed 102858600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 102958600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 103058600ac3SJames Wright 103158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 103258600ac3SJames Wright **/ 103358600ac3SJames Wright PetscErrorCode MatCeedRestoreLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 103458600ac3SJames Wright PetscFunctionBeginUser; 103558600ac3SJames Wright if (X_loc) PetscCall(VecDestroy(X_loc)); 103658600ac3SJames Wright if (Y_loc_transpose) PetscCall(VecDestroy(Y_loc_transpose)); 103758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 103858600ac3SJames Wright } 103958600ac3SJames Wright 104058600ac3SJames Wright /** 104158600ac3SJames Wright @brief Get libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 104258600ac3SJames Wright 104358600ac3SJames Wright Not collective across MPI processes. 104458600ac3SJames Wright 104558600ac3SJames Wright @param[in,out] mat MatCeed 104658600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 104758600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 104858600ac3SJames Wright 104958600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 105058600ac3SJames Wright **/ 105158600ac3SJames Wright PetscErrorCode MatCeedGetCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 105258600ac3SJames Wright MatCeedContext ctx; 105358600ac3SJames Wright 105458600ac3SJames Wright PetscFunctionBeginUser; 105558600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 105658600ac3SJames Wright if (op_mult) { 105758600ac3SJames Wright *op_mult = NULL; 105850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult, op_mult)); 105958600ac3SJames Wright } 106058600ac3SJames Wright if (op_mult_transpose) { 106158600ac3SJames Wright *op_mult_transpose = NULL; 106250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult_transpose, op_mult_transpose)); 106358600ac3SJames Wright } 106458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 106558600ac3SJames Wright } 106658600ac3SJames Wright 106758600ac3SJames Wright /** 106858600ac3SJames Wright @brief Restore libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 106958600ac3SJames Wright 107058600ac3SJames Wright Not collective across MPI processes. 107158600ac3SJames Wright 107258600ac3SJames Wright @param[in,out] mat MatCeed 107358600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 107458600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 107558600ac3SJames Wright 107658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 107758600ac3SJames Wright **/ 107858600ac3SJames Wright PetscErrorCode MatCeedRestoreCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 107958600ac3SJames Wright MatCeedContext ctx; 108058600ac3SJames Wright 108158600ac3SJames Wright PetscFunctionBeginUser; 108258600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 108350f50432SJames Wright if (op_mult) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult)); 108450f50432SJames Wright if (op_mult_transpose) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult_transpose)); 108558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 108658600ac3SJames Wright } 108758600ac3SJames Wright 108858600ac3SJames Wright /** 108958600ac3SJames Wright @brief Set `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 109058600ac3SJames Wright 109158600ac3SJames Wright Not collective across MPI processes. 109258600ac3SJames Wright 109358600ac3SJames Wright @param[in,out] mat MatCeed 109458600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 109558600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 109658600ac3SJames Wright 109758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 109858600ac3SJames Wright **/ 109958600ac3SJames Wright PetscErrorCode MatCeedSetLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 110058600ac3SJames Wright MatCeedContext ctx; 110158600ac3SJames Wright 110258600ac3SJames Wright PetscFunctionBeginUser; 110358600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 110458600ac3SJames Wright if (log_event_mult) ctx->log_event_mult = log_event_mult; 110558600ac3SJames Wright if (log_event_mult_transpose) ctx->log_event_mult_transpose = log_event_mult_transpose; 110658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 110758600ac3SJames Wright } 110858600ac3SJames Wright 110958600ac3SJames Wright /** 111058600ac3SJames Wright @brief Get `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 111158600ac3SJames Wright 111258600ac3SJames Wright Not collective across MPI processes. 111358600ac3SJames Wright 111458600ac3SJames Wright @param[in,out] mat MatCeed 111558600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 111658600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 111758600ac3SJames Wright 111858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 111958600ac3SJames Wright **/ 112058600ac3SJames Wright PetscErrorCode MatCeedGetLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 112158600ac3SJames Wright MatCeedContext ctx; 112258600ac3SJames Wright 112358600ac3SJames Wright PetscFunctionBeginUser; 112458600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 112558600ac3SJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_mult; 112658600ac3SJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_mult_transpose; 112758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 112858600ac3SJames Wright } 112958600ac3SJames Wright 1130*c63b910fSJames Wright /** 1131*c63b910fSJames Wright @brief Set `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1132*c63b910fSJames Wright 1133*c63b910fSJames Wright Not collective across MPI processes. 1134*c63b910fSJames Wright 1135*c63b910fSJames Wright @param[in,out] mat MatCeed 1136*c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1137*c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1138*c63b910fSJames Wright 1139*c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1140*c63b910fSJames Wright **/ 1141*c63b910fSJames Wright PetscErrorCode MatCeedSetCeedOperatorLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 1142*c63b910fSJames Wright MatCeedContext ctx; 1143*c63b910fSJames Wright 1144*c63b910fSJames Wright PetscFunctionBeginUser; 1145*c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1146*c63b910fSJames Wright if (log_event_mult) ctx->log_event_ceed_mult = log_event_mult; 1147*c63b910fSJames Wright if (log_event_mult_transpose) ctx->log_event_ceed_mult_transpose = log_event_mult_transpose; 1148*c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1149*c63b910fSJames Wright } 1150*c63b910fSJames Wright 1151*c63b910fSJames Wright /** 1152*c63b910fSJames Wright @brief Get `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1153*c63b910fSJames Wright 1154*c63b910fSJames Wright Not collective across MPI processes. 1155*c63b910fSJames Wright 1156*c63b910fSJames Wright @param[in,out] mat MatCeed 1157*c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1158*c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1159*c63b910fSJames Wright 1160*c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1161*c63b910fSJames Wright **/ 1162*c63b910fSJames Wright PetscErrorCode MatCeedGetCeedOperatorLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 1163*c63b910fSJames Wright MatCeedContext ctx; 1164*c63b910fSJames Wright 1165*c63b910fSJames Wright PetscFunctionBeginUser; 1166*c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1167*c63b910fSJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_ceed_mult; 1168*c63b910fSJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_ceed_mult_transpose; 1169*c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1170*c63b910fSJames Wright } 1171*c63b910fSJames Wright 117258600ac3SJames Wright // ----------------------------------------------------------------------------- 117358600ac3SJames Wright // Operator context data 117458600ac3SJames Wright // ----------------------------------------------------------------------------- 117558600ac3SJames Wright 117658600ac3SJames Wright /** 117758600ac3SJames Wright @brief Setup context data for operator application. 117858600ac3SJames Wright 117958600ac3SJames Wright Collective across MPI processes. 118058600ac3SJames Wright 118158600ac3SJames Wright @param[in] dm_x Input `DM` 118258600ac3SJames Wright @param[in] dm_y Output `DM` 118358600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 118458600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 118558600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 118658600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 118758600ac3SJames Wright @param[in] log_event_mult `PetscLogEvent` for forward evaluation 118858600ac3SJames Wright @param[in] log_event_mult_transpose `PetscLogEvent` for transpose evaluation 1189*c63b910fSJames Wright @param[in] log_event_ceed_mult `PetscLogEvent` for forward `CeedOperator` evaluation 1190*c63b910fSJames Wright @param[in] log_event_ceed_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation 119158600ac3SJames Wright @param[out] ctx Context data for operator evaluation 119258600ac3SJames Wright 119358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 119458600ac3SJames Wright **/ 119558600ac3SJames Wright PetscErrorCode MatCeedContextCreate(DM dm_x, DM dm_y, Vec X_loc, Vec Y_loc_transpose, CeedOperator op_mult, CeedOperator op_mult_transpose, 1196*c63b910fSJames Wright PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose, PetscLogEvent log_event_ceed_mult, 1197*c63b910fSJames Wright PetscLogEvent log_event_ceed_mult_transpose, MatCeedContext *ctx) { 119858600ac3SJames Wright CeedSize x_loc_len, y_loc_len; 119958600ac3SJames Wright 120058600ac3SJames Wright PetscFunctionBeginUser; 120158600ac3SJames Wright 120258600ac3SJames Wright // Allocate 120358600ac3SJames Wright PetscCall(PetscNew(ctx)); 120458600ac3SJames Wright (*ctx)->ref_count = 1; 120558600ac3SJames Wright 120658600ac3SJames Wright // Logging 120758600ac3SJames Wright (*ctx)->log_event_mult = log_event_mult; 120858600ac3SJames Wright (*ctx)->log_event_mult_transpose = log_event_mult_transpose; 1209*c63b910fSJames Wright (*ctx)->log_event_ceed_mult = log_event_ceed_mult; 1210*c63b910fSJames Wright (*ctx)->log_event_ceed_mult_transpose = log_event_ceed_mult_transpose; 121158600ac3SJames Wright 121258600ac3SJames Wright // PETSc objects 121340d80af1SJames Wright PetscCall(DMReferenceCopy(dm_x, &(*ctx)->dm_x)); 121440d80af1SJames Wright PetscCall(DMReferenceCopy(dm_y, &(*ctx)->dm_y)); 121540d80af1SJames Wright if (X_loc) PetscCall(VecReferenceCopy(X_loc, &(*ctx)->X_loc)); 121640d80af1SJames Wright if (Y_loc_transpose) PetscCall(VecReferenceCopy(Y_loc_transpose, &(*ctx)->Y_loc_transpose)); 121758600ac3SJames Wright 121858600ac3SJames Wright // Memtype 121958600ac3SJames Wright { 122058600ac3SJames Wright const PetscScalar *x; 122158600ac3SJames Wright Vec X; 122258600ac3SJames Wright 122358600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &X)); 122458600ac3SJames Wright PetscCall(VecGetArrayReadAndMemType(X, &x, &(*ctx)->mem_type)); 122558600ac3SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X, &x)); 122658600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &X)); 122758600ac3SJames Wright } 122858600ac3SJames Wright 122958600ac3SJames Wright // libCEED objects 123058600ac3SJames Wright PetscCheck(CeedOperatorGetCeed(op_mult, &(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, 123158600ac3SJames Wright "retrieving Ceed context object failed"); 123250f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedReference((*ctx)->ceed)); 123350f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetActiveVectorLengths(op_mult, &x_loc_len, &y_loc_len)); 123450f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult, &(*ctx)->op_mult)); 123550f50432SJames Wright if (op_mult_transpose) PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult_transpose, &(*ctx)->op_mult_transpose)); 123650f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, x_loc_len, &(*ctx)->x_loc)); 123750f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, y_loc_len, &(*ctx)->y_loc)); 123858600ac3SJames Wright 123958600ac3SJames Wright // Flop counting 124058600ac3SJames Wright { 124158600ac3SJames Wright CeedSize ceed_flops_estimate = 0; 124258600ac3SJames Wright 124350f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult, &ceed_flops_estimate)); 124458600ac3SJames Wright (*ctx)->flops_mult = ceed_flops_estimate; 124558600ac3SJames Wright if (op_mult_transpose) { 124650f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult_transpose, &ceed_flops_estimate)); 124758600ac3SJames Wright (*ctx)->flops_mult_transpose = ceed_flops_estimate; 124858600ac3SJames Wright } 124958600ac3SJames Wright } 125058600ac3SJames Wright 125158600ac3SJames Wright // Check sizes 125258600ac3SJames Wright if (x_loc_len > 0 || y_loc_len > 0) { 125358600ac3SJames Wright CeedSize ctx_x_loc_len, ctx_y_loc_len; 125458600ac3SJames Wright PetscInt X_loc_len, dm_x_loc_len, Y_loc_len, dm_y_loc_len; 125558600ac3SJames Wright Vec dm_X_loc, dm_Y_loc; 125658600ac3SJames Wright 125758600ac3SJames Wright // -- Input 125858600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &dm_X_loc)); 125958600ac3SJames Wright PetscCall(VecGetLocalSize(dm_X_loc, &dm_x_loc_len)); 126058600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &dm_X_loc)); 126150f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->x_loc, &ctx_x_loc_len)); 12624c17272bSJames Wright if (X_loc) { 12634c17272bSJames Wright PetscCall(VecGetLocalSize(X_loc, &X_loc_len)); 12644c17272bSJames Wright PetscCheck(X_loc_len == dm_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 12654c17272bSJames Wright "X_loc (%" PetscInt_FMT ") must match dm_x (%" PetscInt_FMT ") dimensions", X_loc_len, dm_x_loc_len); 12664c17272bSJames Wright } 12674c17272bSJames Wright PetscCheck(x_loc_len == dm_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, "op (%" CeedSize_FMT ") must match dm_x (%" PetscInt_FMT ") dimensions", 12684c17272bSJames Wright x_loc_len, dm_x_loc_len); 12694c17272bSJames Wright PetscCheck(x_loc_len == ctx_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, "x_loc (%" CeedSize_FMT ") must match op dimensions (%" CeedSize_FMT ")", 12704c17272bSJames Wright x_loc_len, ctx_x_loc_len); 127158600ac3SJames Wright 127258600ac3SJames Wright // -- Output 127358600ac3SJames Wright PetscCall(DMGetLocalVector(dm_y, &dm_Y_loc)); 127458600ac3SJames Wright PetscCall(VecGetLocalSize(dm_Y_loc, &dm_y_loc_len)); 127558600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_y, &dm_Y_loc)); 127650f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->y_loc, &ctx_y_loc_len)); 12774c17272bSJames Wright PetscCheck(ctx_y_loc_len == dm_y_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, "op (%" CeedSize_FMT ") must match dm_y (%" PetscInt_FMT ") dimensions", 12784c17272bSJames Wright ctx_y_loc_len, dm_y_loc_len); 127958600ac3SJames Wright 128058600ac3SJames Wright // -- Transpose 128158600ac3SJames Wright if (Y_loc_transpose) { 128258600ac3SJames Wright PetscCall(VecGetLocalSize(Y_loc_transpose, &Y_loc_len)); 12834c17272bSJames Wright PetscCheck(Y_loc_len == dm_y_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 12844c17272bSJames Wright "Y_loc_transpose (%" PetscInt_FMT ") must match dm_y (%" PetscInt_FMT ") dimensions", Y_loc_len, dm_y_loc_len); 128558600ac3SJames Wright } 128658600ac3SJames Wright } 128758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 128858600ac3SJames Wright } 128958600ac3SJames Wright 129058600ac3SJames Wright /** 129158600ac3SJames Wright @brief Increment reference counter for `MATCEED` context. 129258600ac3SJames Wright 129358600ac3SJames Wright Not collective across MPI processes. 129458600ac3SJames Wright 129558600ac3SJames Wright @param[in,out] ctx Context data 129658600ac3SJames Wright 129758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 129858600ac3SJames Wright **/ 129958600ac3SJames Wright PetscErrorCode MatCeedContextReference(MatCeedContext ctx) { 130058600ac3SJames Wright PetscFunctionBeginUser; 130158600ac3SJames Wright ctx->ref_count++; 130258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 130358600ac3SJames Wright } 130458600ac3SJames Wright 130558600ac3SJames Wright /** 130658600ac3SJames Wright @brief Copy reference for `MATCEED`. 130758600ac3SJames Wright Note: If `ctx_copy` is non-null, it is assumed to be a valid pointer to a `MatCeedContext`. 130858600ac3SJames Wright 130958600ac3SJames Wright Not collective across MPI processes. 131058600ac3SJames Wright 131158600ac3SJames Wright @param[in] ctx Context data 131258600ac3SJames Wright @param[out] ctx_copy Copy of pointer to context data 131358600ac3SJames Wright 131458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 131558600ac3SJames Wright **/ 131658600ac3SJames Wright PetscErrorCode MatCeedContextReferenceCopy(MatCeedContext ctx, MatCeedContext *ctx_copy) { 131758600ac3SJames Wright PetscFunctionBeginUser; 131858600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 131958600ac3SJames Wright PetscCall(MatCeedContextDestroy(*ctx_copy)); 132058600ac3SJames Wright *ctx_copy = ctx; 132158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 132258600ac3SJames Wright } 132358600ac3SJames Wright 132458600ac3SJames Wright /** 132558600ac3SJames Wright @brief Destroy context data for operator application. 132658600ac3SJames Wright 132758600ac3SJames Wright Collective across MPI processes. 132858600ac3SJames Wright 132958600ac3SJames Wright @param[in,out] ctx Context data for operator evaluation 133058600ac3SJames Wright 133158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 133258600ac3SJames Wright **/ 133358600ac3SJames Wright PetscErrorCode MatCeedContextDestroy(MatCeedContext ctx) { 133458600ac3SJames Wright PetscFunctionBeginUser; 133558600ac3SJames Wright if (!ctx || --ctx->ref_count > 0) PetscFunctionReturn(PETSC_SUCCESS); 133658600ac3SJames Wright 133758600ac3SJames Wright // PETSc objects 133858600ac3SJames Wright PetscCall(DMDestroy(&ctx->dm_x)); 133958600ac3SJames Wright PetscCall(DMDestroy(&ctx->dm_y)); 134058600ac3SJames Wright PetscCall(VecDestroy(&ctx->X_loc)); 134158600ac3SJames Wright PetscCall(VecDestroy(&ctx->Y_loc_transpose)); 134258600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 134358600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 134440d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 134558600ac3SJames Wright PetscCall(PetscFree(ctx->mats_assembled_full)); 134658600ac3SJames Wright PetscCall(PetscFree(ctx->mats_assembled_pbd)); 134758600ac3SJames Wright 134858600ac3SJames Wright // libCEED objects 134950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->x_loc)); 135050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->y_loc)); 135150f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->coo_values_full)); 135250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->coo_values_pbd)); 135350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorDestroy(&ctx->op_mult)); 135450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorDestroy(&ctx->op_mult_transpose)); 135558600ac3SJames Wright PetscCheck(CeedDestroy(&ctx->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, "destroying libCEED context object failed"); 135658600ac3SJames Wright 135758600ac3SJames Wright // Deallocate 135858600ac3SJames Wright ctx->is_destroyed = PETSC_TRUE; // Flag as destroyed in case someone has stale ref 135958600ac3SJames Wright PetscCall(PetscFree(ctx)); 136058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 136158600ac3SJames Wright } 136258600ac3SJames Wright 136358600ac3SJames Wright /** 136458600ac3SJames Wright @brief Compute the diagonal of an operator via libCEED. 136558600ac3SJames Wright 136658600ac3SJames Wright Collective across MPI processes. 136758600ac3SJames Wright 136858600ac3SJames Wright @param[in] A `MATCEED` 136958600ac3SJames Wright @param[out] D Vector holding operator diagonal 137058600ac3SJames Wright 137158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 137258600ac3SJames Wright **/ 137358600ac3SJames Wright PetscErrorCode MatGetDiagonal_Ceed(Mat A, Vec D) { 137458600ac3SJames Wright PetscMemType mem_type; 137558600ac3SJames Wright Vec D_loc; 137658600ac3SJames Wright MatCeedContext ctx; 137758600ac3SJames Wright 137858600ac3SJames Wright PetscFunctionBeginUser; 137958600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 138058600ac3SJames Wright 138158600ac3SJames Wright // Place PETSc vector in libCEED vector 1382*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 138358600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &D_loc)); 1384a7dac1d5SJames Wright PetscCall(VecPetscToCeed(D_loc, &mem_type, ctx->x_loc)); 138558600ac3SJames Wright 138658600ac3SJames Wright // Compute Diagonal 1387*c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 138850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleDiagonal(ctx->op_mult, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1389*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 139058600ac3SJames Wright 139158600ac3SJames Wright // Restore PETSc vector 1392a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, mem_type, D_loc)); 139358600ac3SJames Wright 139458600ac3SJames Wright // Local-to-Global 139558600ac3SJames Wright PetscCall(VecZeroEntries(D)); 139658600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, D_loc, ADD_VALUES, D)); 139758600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &D_loc)); 1398*c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 139958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 140058600ac3SJames Wright } 140158600ac3SJames Wright 140258600ac3SJames Wright /** 140358600ac3SJames Wright @brief Compute `A X = Y` for a `MATCEED`. 140458600ac3SJames Wright 140558600ac3SJames Wright Collective across MPI processes. 140658600ac3SJames Wright 140758600ac3SJames Wright @param[in] A `MATCEED` 140858600ac3SJames Wright @param[in] X Input PETSc vector 140958600ac3SJames Wright @param[out] Y Output PETSc vector 141058600ac3SJames Wright 141158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 141258600ac3SJames Wright **/ 141358600ac3SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 141458600ac3SJames Wright MatCeedContext ctx; 141558600ac3SJames Wright 141658600ac3SJames Wright PetscFunctionBeginUser; 141758600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1418*c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult, A, X, Y, NULL)); 141958600ac3SJames Wright 142058600ac3SJames Wright { 142158600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 142258600ac3SJames Wright Vec X_loc = ctx->X_loc, Y_loc; 142358600ac3SJames Wright 142458600ac3SJames Wright // Get local vectors 142558600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 142658600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 142758600ac3SJames Wright 142858600ac3SJames Wright // Global-to-local 142958600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc)); 143058600ac3SJames Wright 143158600ac3SJames Wright // Setup libCEED vectors 1432a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 143358600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc)); 1434a7dac1d5SJames Wright PetscCall(VecPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 143558600ac3SJames Wright 143658600ac3SJames Wright // Apply libCEED operator 143758600ac3SJames Wright PetscCall(PetscLogGpuTimeBegin()); 1438*c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult, A, X, Y, NULL)); 143950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult, ctx->x_loc, ctx->y_loc, CEED_REQUEST_IMMEDIATE)); 1440*c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult, A, X, Y, NULL)); 144158600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 144258600ac3SJames Wright 144358600ac3SJames Wright // Restore PETSc vectors 1444a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1445a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 144658600ac3SJames Wright 144758600ac3SJames Wright // Local-to-global 144858600ac3SJames Wright PetscCall(VecZeroEntries(Y)); 144958600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y)); 145058600ac3SJames Wright 145158600ac3SJames Wright // Restore local vectors, as needed 145258600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 145358600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 145458600ac3SJames Wright } 145558600ac3SJames Wright 145658600ac3SJames Wright // Log flops 145758600ac3SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult)); 145858600ac3SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult)); 1459*c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult, A, X, Y, NULL)); 146058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 146158600ac3SJames Wright } 146258600ac3SJames Wright 146358600ac3SJames Wright /** 146458600ac3SJames Wright @brief Compute `A^T Y = X` for a `MATCEED`. 146558600ac3SJames Wright 146658600ac3SJames Wright Collective across MPI processes. 146758600ac3SJames Wright 146858600ac3SJames Wright @param[in] A `MATCEED` 146958600ac3SJames Wright @param[in] Y Input PETSc vector 147058600ac3SJames Wright @param[out] X Output PETSc vector 147158600ac3SJames Wright 147258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 147358600ac3SJames Wright **/ 147458600ac3SJames Wright PetscErrorCode MatMultTranspose_Ceed(Mat A, Vec Y, Vec X) { 147558600ac3SJames Wright MatCeedContext ctx; 147658600ac3SJames Wright 147758600ac3SJames Wright PetscFunctionBeginUser; 147858600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1479*c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult_transpose, A, Y, X, NULL)); 148058600ac3SJames Wright 148158600ac3SJames Wright { 148258600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 148358600ac3SJames Wright Vec X_loc, Y_loc = ctx->Y_loc_transpose; 148458600ac3SJames Wright 148558600ac3SJames Wright // Get local vectors 148658600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 148758600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 148858600ac3SJames Wright 148958600ac3SJames Wright // Global-to-local 149058600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_y, Y, INSERT_VALUES, Y_loc)); 149158600ac3SJames Wright 149258600ac3SJames Wright // Setup libCEED vectors 1493a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 149458600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 1495a7dac1d5SJames Wright PetscCall(VecPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 149658600ac3SJames Wright 149758600ac3SJames Wright // Apply libCEED operator 149858600ac3SJames Wright PetscCall(PetscLogGpuTimeBegin()); 1499*c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 150050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult_transpose, ctx->y_loc, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1501*c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 150258600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 150358600ac3SJames Wright 150458600ac3SJames Wright // Restore PETSc vectors 1505a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1506a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 150758600ac3SJames Wright 150858600ac3SJames Wright // Local-to-global 150958600ac3SJames Wright PetscCall(VecZeroEntries(X)); 151058600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, X_loc, ADD_VALUES, X)); 151158600ac3SJames Wright 151258600ac3SJames Wright // Restore local vectors, as needed 151358600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 151458600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 151558600ac3SJames Wright } 151658600ac3SJames Wright 151758600ac3SJames Wright // Log flops 151858600ac3SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult_transpose)); 151958600ac3SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult_transpose)); 1520*c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult_transpose, A, Y, X, NULL)); 152158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 152258600ac3SJames Wright } 1523