1c8564c30SJames Wright /// @file 25037d55dSJames Wright /// MatCEED implementation 3c8564c30SJames Wright 4c8564c30SJames Wright #include <ceed.h> 5c8564c30SJames Wright #include <ceed/backend.h> 6c8564c30SJames Wright #include <mat-ceed-impl.h> 7c8564c30SJames Wright #include <mat-ceed.h> 85037d55dSJames Wright #include <petsc-ceed-utils.h> 95037d55dSJames Wright #include <petsc-ceed.h> 10*243afec9SJames Wright #include <petscdm.h> 11*243afec9SJames Wright #include <petscmat.h> 12*243afec9SJames Wright #include <stdbool.h> 13*243afec9SJames Wright #include <stdio.h> 14c8564c30SJames Wright #include <stdlib.h> 15c8564c30SJames Wright #include <string.h> 16c8564c30SJames Wright 17c8564c30SJames Wright PetscClassId MATCEED_CLASSID; 1843327b86SJames Wright PetscLogEvent MATCEED_MULT, MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE, MATCEED_MULT_TRANSPOSE_CEEDOP, MATCEED_ASSEMBLE_DIAGONAL, 1943327b86SJames Wright MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, MATCEED_SETUP_PBDIAGONAL, MATCEED_SETUP_PBDIAGONAL_CEEDOP, MATCEED_ASSEMBLE_PBDIAGONAL, 2043327b86SJames Wright MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, MATCEED_SETUP_FULL, MATCEED_SETUP_FULL_CEEDOP, MATCEED_ASSEMBLE_FULL, MATCEED_ASSEMBLE_FULL_CEEDOP; 21c8564c30SJames Wright 22c8564c30SJames Wright /** 23c8564c30SJames Wright @brief Register MATCEED log events. 24c8564c30SJames Wright 25c8564c30SJames Wright Not collective across MPI processes. 26c8564c30SJames Wright 27c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 28c8564c30SJames Wright **/ 29c8564c30SJames Wright static PetscErrorCode MatCeedRegisterLogEvents() { 305037d55dSJames Wright static PetscBool registered = PETSC_FALSE; 31c8564c30SJames Wright 32c8564c30SJames Wright PetscFunctionBeginUser; 33c8564c30SJames Wright if (registered) PetscFunctionReturn(PETSC_SUCCESS); 3443327b86SJames Wright PetscCall(PetscClassIdRegister("MatCEED", &MATCEED_CLASSID)); 3543327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDMul", MATCEED_CLASSID, &MATCEED_MULT)); 3643327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulCeed", MATCEED_CLASSID, &MATCEED_MULT_CEEDOP)); 3743327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulT", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE)); 3843327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulTCeed", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE_CEEDOP)); 3943327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmDiag", MATCEED_CLASSID, &MATCEED_ASSEMBLE_DIAGONAL)); 4043327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSU", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL)); 4143327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL_CEEDOP)); 4243327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBD", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL)); 4343327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP)); 4443327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSU", MATCEED_CLASSID, &MATCEED_SETUP_FULL)); 4543327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_FULL_CEEDOP)); 4643327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsm", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL)); 4743327b86SJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL_CEEDOP)); 485037d55dSJames Wright registered = PETSC_TRUE; 49c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 50c8564c30SJames Wright } 51c8564c30SJames Wright 52c8564c30SJames Wright /** 53c8564c30SJames Wright @brief Assemble the point block diagonal of a `MATCEED` into a `MATAIJ` or similar. 54c8564c30SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 55c8564c30SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 56c8564c30SJames Wright 57c8564c30SJames Wright Collective across MPI processes. 58c8564c30SJames Wright 59c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to assemble 60c8564c30SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 61c8564c30SJames Wright 62c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 63c8564c30SJames Wright **/ 64c8564c30SJames Wright static PetscErrorCode MatCeedAssemblePointBlockDiagonalCOO(Mat mat_ceed, Mat mat_coo) { 65c8564c30SJames Wright MatCeedContext ctx; 66c8564c30SJames Wright 67c8564c30SJames Wright PetscFunctionBeginUser; 68c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 69c8564c30SJames Wright 70c8564c30SJames Wright // Check if COO pattern set 71c8564c30SJames Wright { 72c8564c30SJames Wright PetscInt index = -1; 73c8564c30SJames Wright 74c8564c30SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 75c8564c30SJames Wright if (ctx->mats_assembled_pbd[i] == mat_coo) index = i; 76c8564c30SJames Wright } 77c8564c30SJames Wright if (index == -1) { 78c8564c30SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 79c8564c30SJames Wright CeedInt *rows_ceed, *cols_ceed; 80c8564c30SJames Wright PetscCount num_entries; 81c8564c30SJames Wright PetscLogStage stage_amg_setup; 82c8564c30SJames Wright 83c8564c30SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 8443327b86SJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 85c8564c30SJames Wright if (stage_amg_setup == -1) { 8643327b86SJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 87c8564c30SJames Wright } 88c8564c30SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 8943327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 9043327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 9154831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonalSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 9243327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 93d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 94d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 95c8564c30SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 96c8564c30SJames Wright free(rows_petsc); 97c8564c30SJames Wright free(cols_petsc); 9854831c5fSJames Wright if (!ctx->coo_values_pbd) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_pbd)); 99c8564c30SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_pbd * sizeof(Mat), &ctx->mats_assembled_pbd)); 100c8564c30SJames Wright ctx->mats_assembled_pbd[ctx->num_mats_assembled_pbd - 1] = mat_coo; 10143327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 102c8564c30SJames Wright PetscCall(PetscLogStagePop()); 103c8564c30SJames Wright } 104c8564c30SJames Wright } 105c8564c30SJames Wright 106c8564c30SJames Wright // Assemble mat_ceed 10743327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 108c8564c30SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 109c8564c30SJames Wright { 110c8564c30SJames Wright const CeedScalar *values; 111c8564c30SJames Wright MatType mat_type; 112c8564c30SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 113c8564c30SJames Wright PetscBool is_spd, is_spd_known; 114c8564c30SJames Wright 115c8564c30SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 116c8564c30SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 117c8564c30SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 118c8564c30SJames Wright else mem_type = CEED_MEM_HOST; 119c8564c30SJames Wright 12043327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 12154831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonal(ctx->op_mult, ctx->coo_values_pbd, CEED_REQUEST_IMMEDIATE)); 12243327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 12354831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_pbd, mem_type, &values)); 124c8564c30SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 125c8564c30SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 126c8564c30SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 12754831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_pbd, &values)); 128c8564c30SJames Wright } 129c8564c30SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 13043327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 131c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 132c8564c30SJames Wright } 133c8564c30SJames Wright 134c8564c30SJames Wright /** 135c8564c30SJames Wright @brief Assemble inner `Mat` for diagonal `PC` operations 136c8564c30SJames Wright 137c8564c30SJames Wright Collective across MPI processes. 138c8564c30SJames Wright 139c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to invert 140c8564c30SJames Wright @param[in] use_ceed_pbd Boolean flag to use libCEED PBD assembly 141c8564c30SJames Wright @param[out] mat_inner Inner `Mat` for diagonal operations 142c8564c30SJames Wright 143c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 144c8564c30SJames Wright **/ 145c8564c30SJames Wright static PetscErrorCode MatCeedAssembleInnerBlockDiagonalMat(Mat mat_ceed, PetscBool use_ceed_pbd, Mat *mat_inner) { 146c8564c30SJames Wright MatCeedContext ctx; 147c8564c30SJames Wright 148c8564c30SJames Wright PetscFunctionBeginUser; 149c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 150c8564c30SJames Wright if (use_ceed_pbd) { 151c8564c30SJames Wright // Check if COO pattern set 1525037d55dSJames Wright if (!ctx->mat_assembled_pbd_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_pbd_internal)); 153c8564c30SJames Wright 154c8564c30SJames Wright // Assemble mat_assembled_full_internal 155c8564c30SJames Wright PetscCall(MatCeedAssemblePointBlockDiagonalCOO(mat_ceed, ctx->mat_assembled_pbd_internal)); 156c8564c30SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_pbd_internal; 157c8564c30SJames Wright } else { 158c8564c30SJames Wright // Check if COO pattern set 1595037d55dSJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 160c8564c30SJames Wright 161c8564c30SJames Wright // Assemble mat_assembled_full_internal 162c8564c30SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 163c8564c30SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_full_internal; 164c8564c30SJames Wright } 165c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 166c8564c30SJames Wright } 167c8564c30SJames Wright 168c8564c30SJames Wright /** 169*243afec9SJames Wright @brief Get `MATCEED` variable block diagonal for Jacobi. 170*243afec9SJames Wright 171*243afec9SJames Wright Collective across MPI processes. 172*243afec9SJames Wright 173*243afec9SJames Wright @param[in] mat_ceed `MATCEED` to invert 174*243afec9SJames Wright @param[out] mat_vblock The variable diagonal block matrix 175*243afec9SJames Wright 176*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 177*243afec9SJames Wright **/ 178*243afec9SJames Wright static PetscErrorCode MatGetVariableBlockDiagonal_Ceed(Mat mat_ceed, Mat *mat_vblock) { 179*243afec9SJames Wright MatCeedContext ctx; 180*243afec9SJames Wright 181*243afec9SJames Wright PetscFunctionBeginUser; 182*243afec9SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 183*243afec9SJames Wright 184*243afec9SJames Wright // Assemble inner mat if needed 185*243afec9SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_vpbd_valid, mat_vblock)); 186*243afec9SJames Wright PetscCall(PetscObjectReference((PetscObject)*mat_vblock)); 187*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 188*243afec9SJames Wright } 189*243afec9SJames Wright 190*243afec9SJames Wright /** 191*243afec9SJames Wright @brief Get `MATCEED` block diagonal for Jacobi. 192*243afec9SJames Wright 193*243afec9SJames Wright Collective across MPI processes. 194*243afec9SJames Wright 195*243afec9SJames Wright @param[in] mat_ceed `MATCEED` to invert 196*243afec9SJames Wright @param[out] mat_block The variable diagonal block matrix 197*243afec9SJames Wright 198*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 199*243afec9SJames Wright **/ 200*243afec9SJames Wright static PetscErrorCode MatGetBlockDiagonal_Ceed(Mat mat_ceed, Mat *mat_block) { 201*243afec9SJames Wright MatCeedContext ctx; 202*243afec9SJames Wright 203*243afec9SJames Wright PetscFunctionBeginUser; 204*243afec9SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 205*243afec9SJames Wright 206*243afec9SJames Wright // Assemble inner mat if needed 207*243afec9SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_pbd_valid, mat_block)); 208*243afec9SJames Wright PetscCall(PetscObjectReference((PetscObject)*mat_block)); 209*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 210*243afec9SJames Wright } 211*243afec9SJames Wright 212*243afec9SJames Wright /** 213*243afec9SJames Wright @brief Get on-process diagonal block of `MATCEED` 214*243afec9SJames Wright 215*243afec9SJames Wright This is a block per-process of the diagonal of the global matrix. 216*243afec9SJames Wright This is NOT the diagonal blocks associated with the block size of the matrix (i.e. `MatSetBlockSize()` has no effect on this function). 217c8564c30SJames Wright 218c8564c30SJames Wright Collective across MPI processes. 219c8564c30SJames Wright 220c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to invert 221c8564c30SJames Wright @param[out] mat_block The diagonal block matrix 222c8564c30SJames Wright 223c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 224c8564c30SJames Wright **/ 225c8564c30SJames Wright static PetscErrorCode MatGetDiagonalBlock_Ceed(Mat mat_ceed, Mat *mat_block) { 226c8564c30SJames Wright MatCeedContext ctx; 227c8564c30SJames Wright 228c8564c30SJames Wright PetscFunctionBeginUser; 229c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 230c8564c30SJames Wright 231*243afec9SJames Wright // Check if COO pattern set 232*243afec9SJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 233c8564c30SJames Wright 234*243afec9SJames Wright // Assemble mat_assembled_full_internal 235*243afec9SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 236c8564c30SJames Wright 237*243afec9SJames Wright // Get diagonal block 238*243afec9SJames Wright PetscCall(MatGetDiagonalBlock(ctx->mat_assembled_full_internal, mat_block)); 239c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 240c8564c30SJames Wright } 241c8564c30SJames Wright 2423933d9a0SJames Wright /** 2433933d9a0SJames Wright @brief View `MATCEED`. 2443933d9a0SJames Wright 2453933d9a0SJames Wright Collective across MPI processes. 2463933d9a0SJames Wright 2473933d9a0SJames Wright @param[in] mat_ceed `MATCEED` to view 2483933d9a0SJames Wright @param[in] viewer The visualization context 2493933d9a0SJames Wright 2503933d9a0SJames Wright @return An error code: 0 - success, otherwise - failure 2513933d9a0SJames Wright **/ 2523933d9a0SJames Wright static PetscErrorCode MatView_Ceed(Mat mat_ceed, PetscViewer viewer) { 2533933d9a0SJames Wright PetscBool is_ascii; 2543933d9a0SJames Wright PetscViewerFormat format; 255*243afec9SJames Wright PetscMPIInt size, rank; 2563933d9a0SJames Wright MatCeedContext ctx; 2573933d9a0SJames Wright 2583933d9a0SJames Wright PetscFunctionBeginUser; 2593933d9a0SJames Wright PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2603933d9a0SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 2613933d9a0SJames Wright if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat_ceed), &viewer)); 2623933d9a0SJames Wright 2633933d9a0SJames Wright PetscCall(PetscViewerGetFormat(viewer, &format)); 2643933d9a0SJames Wright PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat_ceed), &size)); 2653933d9a0SJames Wright if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 2663933d9a0SJames Wright 267*243afec9SJames Wright PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat_ceed), &rank)); 268*243afec9SJames Wright if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS); 269*243afec9SJames Wright 2703933d9a0SJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii)); 2713933d9a0SJames Wright { 272*243afec9SJames Wright PetscBool is_detailed = format == PETSC_VIEWER_ASCII_INFO_DETAIL; 273*243afec9SJames Wright char rank_string[16] = {'\0'}; 2743933d9a0SJames Wright FILE *file; 2753933d9a0SJames Wright 276*243afec9SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "MatCEED:\n")); 277*243afec9SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // MatCEED 278*243afec9SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "Default COO MatType: %s\n", ctx->coo_mat_type)); 279*243afec9SJames Wright PetscCall(PetscSNPrintf(rank_string, 16, "on Rank %d", rank)); 280*243afec9SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator Apply %s:\n", is_detailed ? rank_string : "Summary")); 281*243afec9SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "libCEED PB Diagonal Assembly: %s\n", ctx->is_ceed_pbd_valid ? "True" : "False")); 282*243afec9SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "libCEED VPB Diagonal Assembly: %s\n", ctx->is_ceed_vpbd_valid ? "True" : "False")); 2833933d9a0SJames Wright PetscCall(PetscViewerASCIIGetPointer(viewer, &file)); 284*243afec9SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 285*243afec9SJames Wright if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult, file)); 286*243afec9SJames Wright else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult, file)); 287*243afec9SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 2883933d9a0SJames Wright if (ctx->op_mult_transpose) { 289*243afec9SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator ApplyTranspose %s:\n", is_detailed ? rank_string : "Summary")); 290*243afec9SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 291*243afec9SJames Wright if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult_transpose, file)); 292*243afec9SJames Wright else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult_transpose, file)); 293*243afec9SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 2943933d9a0SJames Wright } 295*243afec9SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // MatCEED 2963933d9a0SJames Wright } 2973933d9a0SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2983933d9a0SJames Wright } 2993933d9a0SJames Wright 300c8564c30SJames Wright // ----------------------------------------------------------------------------- 301c8564c30SJames Wright // MatCeed 302c8564c30SJames Wright // ----------------------------------------------------------------------------- 303c8564c30SJames Wright 304c8564c30SJames Wright /** 305c8564c30SJames Wright @brief Create PETSc `Mat` from libCEED operators. 306c8564c30SJames Wright 307c8564c30SJames Wright Collective across MPI processes. 308c8564c30SJames Wright 309c8564c30SJames Wright @param[in] dm_x Input `DM` 310c8564c30SJames Wright @param[in] dm_y Output `DM` 311c8564c30SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 312c8564c30SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 313c8564c30SJames Wright @param[out] mat New MatCeed 314c8564c30SJames Wright 315c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 316c8564c30SJames Wright **/ 317*243afec9SJames Wright PetscErrorCode MatCreateCeed(DM dm_x, DM dm_y, CeedOperator op_mult, CeedOperator op_mult_transpose, Mat *mat) { 318c8564c30SJames Wright PetscInt X_l_size, X_g_size, Y_l_size, Y_g_size; 319c8564c30SJames Wright VecType vec_type; 320c8564c30SJames Wright MatCeedContext ctx; 321c8564c30SJames Wright 322c8564c30SJames Wright PetscFunctionBeginUser; 323c8564c30SJames Wright PetscCall(MatCeedRegisterLogEvents()); 324c8564c30SJames Wright 325c8564c30SJames Wright // Collect context data 326c8564c30SJames Wright PetscCall(DMGetVecType(dm_x, &vec_type)); 327c8564c30SJames Wright { 328c8564c30SJames Wright Vec X; 329c8564c30SJames Wright 330c8564c30SJames Wright PetscCall(DMGetGlobalVector(dm_x, &X)); 331c8564c30SJames Wright PetscCall(VecGetSize(X, &X_g_size)); 332c8564c30SJames Wright PetscCall(VecGetLocalSize(X, &X_l_size)); 333c8564c30SJames Wright PetscCall(DMRestoreGlobalVector(dm_x, &X)); 334c8564c30SJames Wright } 335c8564c30SJames Wright if (dm_y) { 336c8564c30SJames Wright Vec Y; 337c8564c30SJames Wright 338c8564c30SJames Wright PetscCall(DMGetGlobalVector(dm_y, &Y)); 339c8564c30SJames Wright PetscCall(VecGetSize(Y, &Y_g_size)); 340c8564c30SJames Wright PetscCall(VecGetLocalSize(Y, &Y_l_size)); 341c8564c30SJames Wright PetscCall(DMRestoreGlobalVector(dm_y, &Y)); 342c8564c30SJames Wright } else { 343c8564c30SJames Wright dm_y = dm_x; 344c8564c30SJames Wright Y_g_size = X_g_size; 345c8564c30SJames Wright Y_l_size = X_l_size; 346c8564c30SJames Wright } 3475037d55dSJames Wright 348c8564c30SJames Wright // Create context 349c8564c30SJames Wright { 350c8564c30SJames Wright Vec X_loc, Y_loc_transpose = NULL; 351c8564c30SJames Wright 352c8564c30SJames Wright PetscCall(DMCreateLocalVector(dm_x, &X_loc)); 353c8564c30SJames Wright PetscCall(VecZeroEntries(X_loc)); 354c8564c30SJames Wright if (op_mult_transpose) { 355c8564c30SJames Wright PetscCall(DMCreateLocalVector(dm_y, &Y_loc_transpose)); 356c8564c30SJames Wright PetscCall(VecZeroEntries(Y_loc_transpose)); 357c8564c30SJames Wright } 35843327b86SJames Wright PetscCall(MatCeedContextCreate(dm_x, dm_y, X_loc, Y_loc_transpose, op_mult, op_mult_transpose, MATCEED_MULT, MATCEED_MULT_TRANSPOSE, 35943327b86SJames Wright MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE_CEEDOP, &ctx)); 360c8564c30SJames Wright PetscCall(VecDestroy(&X_loc)); 361c8564c30SJames Wright PetscCall(VecDestroy(&Y_loc_transpose)); 362c8564c30SJames Wright } 363c8564c30SJames Wright 364c8564c30SJames Wright // Create mat 365c8564c30SJames Wright PetscCall(MatCreateShell(PetscObjectComm((PetscObject)dm_x), Y_l_size, X_l_size, Y_g_size, X_g_size, ctx, mat)); 366c8564c30SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)*mat, MATCEED)); 367c8564c30SJames Wright // -- Set block and variable block sizes 368c8564c30SJames Wright if (dm_x == dm_y) { 369c8564c30SJames Wright MatType dm_mat_type, dm_mat_type_copy; 370c8564c30SJames Wright Mat temp_mat; 371c8564c30SJames Wright 372c8564c30SJames Wright PetscCall(DMGetMatType(dm_x, &dm_mat_type)); 373c8564c30SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 374c8564c30SJames Wright PetscCall(DMSetMatType(dm_x, MATAIJ)); 375c8564c30SJames Wright PetscCall(DMCreateMatrix(dm_x, &temp_mat)); 376c8564c30SJames Wright PetscCall(DMSetMatType(dm_x, dm_mat_type_copy)); 377c8564c30SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 378c8564c30SJames Wright 379c8564c30SJames Wright { 380c8564c30SJames Wright PetscInt block_size, num_blocks, max_vblock_size = PETSC_INT_MAX; 381c8564c30SJames Wright const PetscInt *vblock_sizes; 382c8564c30SJames Wright 383c8564c30SJames Wright // -- Get block sizes 384c8564c30SJames Wright PetscCall(MatGetBlockSize(temp_mat, &block_size)); 385c8564c30SJames Wright PetscCall(MatGetVariableBlockSizes(temp_mat, &num_blocks, &vblock_sizes)); 386c8564c30SJames Wright { 387c8564c30SJames Wright PetscInt local_min_max[2] = {0}, global_min_max[2] = {0, PETSC_INT_MAX}; 388c8564c30SJames Wright 389c8564c30SJames Wright for (PetscInt i = 0; i < num_blocks; i++) local_min_max[1] = PetscMax(local_min_max[1], vblock_sizes[i]); 390c8564c30SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_min_max, global_min_max)); 391c8564c30SJames Wright max_vblock_size = global_min_max[1]; 392c8564c30SJames Wright } 393c8564c30SJames Wright 394c8564c30SJames Wright // -- Copy block sizes 395c8564c30SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(*mat, block_size)); 396c8564c30SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(*mat, num_blocks, (PetscInt *)vblock_sizes)); 397c8564c30SJames Wright 398c8564c30SJames Wright // -- Check libCEED compatibility 399c8564c30SJames Wright { 400c8564c30SJames Wright bool is_composite; 401c8564c30SJames Wright 402c8564c30SJames Wright ctx->is_ceed_pbd_valid = PETSC_TRUE; 403c8564c30SJames Wright ctx->is_ceed_vpbd_valid = PETSC_TRUE; 40454831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorIsComposite(op_mult, &is_composite)); 405c8564c30SJames Wright if (is_composite) { 406c8564c30SJames Wright CeedInt num_sub_operators; 407c8564c30SJames Wright CeedOperator *sub_operators; 408c8564c30SJames Wright 40954831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetNumSub(op_mult, &num_sub_operators)); 41054831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetSubList(op_mult, &sub_operators)); 411c8564c30SJames Wright for (CeedInt i = 0; i < num_sub_operators; i++) { 412c8564c30SJames Wright CeedInt num_bases, num_comp; 413c8564c30SJames Wright CeedBasis *active_bases; 414c8564c30SJames Wright CeedOperatorAssemblyData assembly_data; 415c8564c30SJames Wright 41654831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(sub_operators[i], &assembly_data)); 41754831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 41854831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 419c8564c30SJames Wright if (num_bases > 1) { 420c8564c30SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 421c8564c30SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 422c8564c30SJames Wright } 423c8564c30SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 424c8564c30SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 425c8564c30SJames Wright } 426c8564c30SJames Wright } else { 427c8564c30SJames Wright // LCOV_EXCL_START 428c8564c30SJames Wright CeedInt num_bases, num_comp; 429c8564c30SJames Wright CeedBasis *active_bases; 430c8564c30SJames Wright CeedOperatorAssemblyData assembly_data; 431c8564c30SJames Wright 43254831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(op_mult, &assembly_data)); 43354831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 43454831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 435c8564c30SJames Wright if (num_bases > 1) { 436c8564c30SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 437c8564c30SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 438c8564c30SJames Wright } 439c8564c30SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 440c8564c30SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 441c8564c30SJames Wright // LCOV_EXCL_STOP 442c8564c30SJames Wright } 443c8564c30SJames Wright { 444c8564c30SJames Wright PetscInt local_is_valid[2], global_is_valid[2]; 445c8564c30SJames Wright 446c8564c30SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_pbd_valid; 447c8564c30SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 448c8564c30SJames Wright ctx->is_ceed_pbd_valid = global_is_valid[0]; 449c8564c30SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_vpbd_valid; 450c8564c30SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 451c8564c30SJames Wright ctx->is_ceed_vpbd_valid = global_is_valid[0]; 452c8564c30SJames Wright } 453c8564c30SJames Wright } 454c8564c30SJames Wright } 455c8564c30SJames Wright PetscCall(MatDestroy(&temp_mat)); 456c8564c30SJames Wright } 457c8564c30SJames Wright // -- Set internal mat type 458c8564c30SJames Wright { 459c8564c30SJames Wright VecType vec_type; 4605037d55dSJames Wright MatType coo_mat_type; 461c8564c30SJames Wright 462c8564c30SJames Wright PetscCall(VecGetType(ctx->X_loc, &vec_type)); 4635037d55dSJames Wright if (strstr(vec_type, VECCUDA)) coo_mat_type = MATAIJCUSPARSE; 4645037d55dSJames Wright else if (strstr(vec_type, VECKOKKOS)) coo_mat_type = MATAIJKOKKOS; 4655037d55dSJames Wright else coo_mat_type = MATAIJ; 4665037d55dSJames Wright PetscCall(PetscStrallocpy(coo_mat_type, &ctx->coo_mat_type)); 467c8564c30SJames Wright } 468c8564c30SJames Wright // -- Set mat operations 469*243afec9SJames Wright PetscCall(MatShellSetContextDestroy(*mat, (PetscCtxDestroyFn *)MatCeedContextDestroy)); 4703933d9a0SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 471c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 472c8564c30SJames Wright if (op_mult_transpose) PetscCall(MatShellSetOperation(*mat, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 473c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 474c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 475*243afec9SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_BLOCK_DIAGONAL, (void (*)(void))MatGetBlockDiagonal_Ceed)); 476*243afec9SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_VBLOCK_DIAGONAL, (void (*)(void))MatGetVariableBlockDiagonal_Ceed)); 477c8564c30SJames Wright PetscCall(MatShellSetVecType(*mat, vec_type)); 478c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 479c8564c30SJames Wright } 480c8564c30SJames Wright 481c8564c30SJames Wright /** 482c8564c30SJames Wright @brief Copy `MATCEED` into a compatible `Mat` with type `MatShell` or `MATCEED`. 483c8564c30SJames Wright 484c8564c30SJames Wright Collective across MPI processes. 485c8564c30SJames Wright 486c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to copy from 487c8564c30SJames Wright @param[out] mat_other `MatShell` or `MATCEED` to copy into 488c8564c30SJames Wright 489c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 490c8564c30SJames Wright **/ 491c8564c30SJames Wright PetscErrorCode MatCeedCopy(Mat mat_ceed, Mat mat_other) { 492c8564c30SJames Wright PetscFunctionBeginUser; 493c8564c30SJames Wright PetscCall(MatCeedRegisterLogEvents()); 494c8564c30SJames Wright 495c8564c30SJames Wright // Check type compatibility 496c8564c30SJames Wright { 4975037d55dSJames Wright PetscBool is_matceed = PETSC_FALSE, is_matshell = PETSC_FALSE; 498c8564c30SJames Wright MatType mat_type_ceed, mat_type_other; 499c8564c30SJames Wright 500c8564c30SJames Wright PetscCall(MatGetType(mat_ceed, &mat_type_ceed)); 5015037d55dSJames Wright PetscCall(PetscStrcmp(mat_type_ceed, MATCEED, &is_matceed)); 5025037d55dSJames Wright PetscCheck(is_matceed, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_ceed must have type " MATCEED); 5035037d55dSJames Wright PetscCall(MatGetType(mat_other, &mat_type_other)); 5045037d55dSJames Wright PetscCall(PetscStrcmp(mat_type_other, MATCEED, &is_matceed)); 5055037d55dSJames Wright PetscCall(PetscStrcmp(mat_type_other, MATSHELL, &is_matceed)); 5065037d55dSJames Wright PetscCheck(is_matceed || is_matshell, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_other must have type " MATCEED " or " MATSHELL); 507c8564c30SJames Wright } 508c8564c30SJames Wright 509c8564c30SJames Wright // Check dimension compatibility 510c8564c30SJames Wright { 511c8564c30SJames 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; 512c8564c30SJames Wright 513c8564c30SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_ceed_size, &X_g_ceed_size)); 514c8564c30SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_ceed_size, &X_l_ceed_size)); 515c8564c30SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_other_size, &X_g_other_size)); 516c8564c30SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_other_size, &X_l_other_size)); 517c8564c30SJames 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) && 518c8564c30SJames Wright (X_l_ceed_size == X_l_other_size), 519c8564c30SJames Wright PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, 520c8564c30SJames Wright "mat_ceed and mat_other must have compatible sizes; found mat_ceed (Global: %" PetscInt_FMT ", %" PetscInt_FMT 521c8564c30SJames Wright "; Local: %" PetscInt_FMT ", %" PetscInt_FMT ") mat_other (Global: %" PetscInt_FMT ", %" PetscInt_FMT "; Local: %" PetscInt_FMT 522c8564c30SJames Wright ", %" PetscInt_FMT ")", 523c8564c30SJames 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); 524c8564c30SJames Wright } 525c8564c30SJames Wright 526c8564c30SJames Wright // Convert 527c8564c30SJames Wright { 528c8564c30SJames Wright VecType vec_type; 529c8564c30SJames Wright MatCeedContext ctx; 530c8564c30SJames Wright 531c8564c30SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)mat_other, MATCEED)); 532c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 533c8564c30SJames Wright PetscCall(MatCeedContextReference(ctx)); 534c8564c30SJames Wright PetscCall(MatShellSetContext(mat_other, ctx)); 535*243afec9SJames Wright PetscCall(MatShellSetContextDestroy(mat_other, (PetscCtxDestroyFn *)MatCeedContextDestroy)); 5363933d9a0SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 537c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 538c8564c30SJames Wright if (ctx->op_mult_transpose) PetscCall(MatShellSetOperation(mat_other, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 539c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 540c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 541*243afec9SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_BLOCK_DIAGONAL, (void (*)(void))MatGetBlockDiagonal_Ceed)); 542*243afec9SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_VBLOCK_DIAGONAL, (void (*)(void))MatGetVariableBlockDiagonal_Ceed)); 543c8564c30SJames Wright { 544c8564c30SJames Wright PetscInt block_size; 545c8564c30SJames Wright 546c8564c30SJames Wright PetscCall(MatGetBlockSize(mat_ceed, &block_size)); 547c8564c30SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(mat_other, block_size)); 548c8564c30SJames Wright } 549c8564c30SJames Wright { 550c8564c30SJames Wright PetscInt num_blocks; 551c8564c30SJames Wright const PetscInt *block_sizes; 552c8564c30SJames Wright 553c8564c30SJames Wright PetscCall(MatGetVariableBlockSizes(mat_ceed, &num_blocks, &block_sizes)); 554c8564c30SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(mat_other, num_blocks, (PetscInt *)block_sizes)); 555c8564c30SJames Wright } 556c8564c30SJames Wright PetscCall(DMGetVecType(ctx->dm_x, &vec_type)); 557c8564c30SJames Wright PetscCall(MatShellSetVecType(mat_other, vec_type)); 558c8564c30SJames Wright } 559c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 560c8564c30SJames Wright } 561c8564c30SJames Wright 562c8564c30SJames Wright /** 563*243afec9SJames Wright @brief Mark `CeedQFunction` data as updated and the `CeedQFunction` as requiring re-assembly for a `MatCEED`. 564*243afec9SJames Wright 565*243afec9SJames Wright Collective across MPI processes. 566*243afec9SJames Wright 567*243afec9SJames Wright @param[in] mat_ceed `MATCEED` 568*243afec9SJames Wright @param[out] update_needed Boolean flag indicating `CeedQFunction` update needed 569*243afec9SJames Wright 570*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 571*243afec9SJames Wright **/ 572*243afec9SJames Wright PetscErrorCode MatCeedSetAssemblyDataUpdateNeeded(Mat mat_ceed, PetscBool update_needed) { 573*243afec9SJames Wright MatCeedContext ctx; 574*243afec9SJames Wright 575*243afec9SJames Wright PetscFunctionBeginUser; 576*243afec9SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 577*243afec9SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult, update_needed)); 578*243afec9SJames Wright if (ctx->op_mult_transpose) { 579*243afec9SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult_transpose, update_needed)); 580*243afec9SJames Wright } 581*243afec9SJames Wright if (update_needed) { 582*243afec9SJames Wright PetscCall(MatAssemblyBegin(mat_ceed, MAT_FINAL_ASSEMBLY)); 583*243afec9SJames Wright PetscCall(MatAssemblyEnd(mat_ceed, MAT_FINAL_ASSEMBLY)); 584*243afec9SJames Wright } 585*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 586*243afec9SJames Wright } 587*243afec9SJames Wright 588*243afec9SJames Wright /** 5895037d55dSJames Wright @brief Setup a `Mat` with the same COO pattern as a `MatCEED`. 5905037d55dSJames Wright 5915037d55dSJames Wright Collective across MPI processes. 5925037d55dSJames Wright 5935037d55dSJames Wright @param[in] mat_ceed `MATCEED` 5945037d55dSJames Wright @param[out] mat_coo Sparse `Mat` with same COO pattern 5955037d55dSJames Wright 5965037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 5975037d55dSJames Wright **/ 5985037d55dSJames Wright PetscErrorCode MatCeedCreateMatCOO(Mat mat_ceed, Mat *mat_coo) { 5995037d55dSJames Wright MatCeedContext ctx; 6005037d55dSJames Wright 6015037d55dSJames Wright PetscFunctionBeginUser; 6025037d55dSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 6035037d55dSJames Wright 6045037d55dSJames 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"); 6055037d55dSJames Wright 6065037d55dSJames Wright // Check cl mat type 6075037d55dSJames Wright { 6085037d55dSJames Wright PetscBool is_coo_mat_type_cl = PETSC_FALSE; 6095037d55dSJames Wright char coo_mat_type_cl[64]; 6105037d55dSJames Wright 6115037d55dSJames Wright // Check for specific CL coo mat type for this Mat 6125037d55dSJames Wright { 6135037d55dSJames Wright const char *mat_ceed_prefix = NULL; 6145037d55dSJames Wright 6155037d55dSJames Wright PetscCall(MatGetOptionsPrefix(mat_ceed, &mat_ceed_prefix)); 6165037d55dSJames Wright PetscOptionsBegin(PetscObjectComm((PetscObject)mat_ceed), mat_ceed_prefix, "", NULL); 6175037d55dSJames Wright PetscCall(PetscOptionsFList("-ceed_coo_mat_type", "Default MATCEED COO assembly MatType", NULL, MatList, coo_mat_type_cl, coo_mat_type_cl, 6185037d55dSJames Wright sizeof(coo_mat_type_cl), &is_coo_mat_type_cl)); 6195037d55dSJames Wright PetscOptionsEnd(); 6205037d55dSJames Wright if (is_coo_mat_type_cl) { 6215037d55dSJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 6225037d55dSJames Wright PetscCall(PetscStrallocpy(coo_mat_type_cl, &ctx->coo_mat_type)); 6235037d55dSJames Wright } 6245037d55dSJames Wright } 6255037d55dSJames Wright } 6265037d55dSJames Wright 6275037d55dSJames Wright // Create sparse matrix 6285037d55dSJames Wright { 6295037d55dSJames Wright MatType dm_mat_type, dm_mat_type_copy; 6305037d55dSJames Wright 6315037d55dSJames Wright PetscCall(DMGetMatType(ctx->dm_x, &dm_mat_type)); 6325037d55dSJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 6335037d55dSJames Wright PetscCall(DMSetMatType(ctx->dm_x, ctx->coo_mat_type)); 6345037d55dSJames Wright PetscCall(DMCreateMatrix(ctx->dm_x, mat_coo)); 6355037d55dSJames Wright PetscCall(DMSetMatType(ctx->dm_x, dm_mat_type_copy)); 6365037d55dSJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 6375037d55dSJames Wright } 6385037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 6395037d55dSJames Wright } 6405037d55dSJames Wright 6415037d55dSJames Wright /** 6425037d55dSJames Wright @brief Setup the COO preallocation `MATCEED` into a `MATAIJ` or similar. 643c8564c30SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 644c8564c30SJames Wright 645c8564c30SJames Wright Collective across MPI processes. 646c8564c30SJames Wright 647c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to assemble 648c8564c30SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 649c8564c30SJames Wright 650c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 651c8564c30SJames Wright **/ 6525037d55dSJames Wright PetscErrorCode MatCeedSetPreallocationCOO(Mat mat_ceed, Mat mat_coo) { 653c8564c30SJames Wright MatCeedContext ctx; 654c8564c30SJames Wright 655c8564c30SJames Wright PetscFunctionBeginUser; 656c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 657c8564c30SJames Wright 658c8564c30SJames Wright { 659c8564c30SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 660c8564c30SJames Wright CeedInt *rows_ceed, *cols_ceed; 661c8564c30SJames Wright PetscCount num_entries; 662c8564c30SJames Wright PetscLogStage stage_amg_setup; 663c8564c30SJames Wright 664c8564c30SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 66543327b86SJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 666c8564c30SJames Wright if (stage_amg_setup == -1) { 66743327b86SJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 668c8564c30SJames Wright } 669c8564c30SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 67043327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 67143327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 67254831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 67343327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 674d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 675d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 676c8564c30SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 677c8564c30SJames Wright free(rows_petsc); 678c8564c30SJames Wright free(cols_petsc); 67954831c5fSJames Wright if (!ctx->coo_values_full) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_full)); 680c8564c30SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_full * sizeof(Mat), &ctx->mats_assembled_full)); 681c8564c30SJames Wright ctx->mats_assembled_full[ctx->num_mats_assembled_full - 1] = mat_coo; 68243327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 683c8564c30SJames Wright PetscCall(PetscLogStagePop()); 684c8564c30SJames Wright } 6855037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 6865037d55dSJames Wright } 6875037d55dSJames Wright 6885037d55dSJames Wright /** 6895037d55dSJames Wright @brief Assemble a `MATCEED` into a `MATAIJ` or similar. 6905037d55dSJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 6915037d55dSJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 6925037d55dSJames Wright 6935037d55dSJames Wright Collective across MPI processes. 6945037d55dSJames Wright 6955037d55dSJames Wright @param[in] mat_ceed `MATCEED` to assemble 6965037d55dSJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 6975037d55dSJames Wright 6985037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 6995037d55dSJames Wright **/ 7005037d55dSJames Wright PetscErrorCode MatCeedAssembleCOO(Mat mat_ceed, Mat mat_coo) { 7015037d55dSJames Wright MatCeedContext ctx; 7025037d55dSJames Wright 7035037d55dSJames Wright PetscFunctionBeginUser; 7045037d55dSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 7055037d55dSJames Wright 7065037d55dSJames Wright // Set COO pattern if needed 7075037d55dSJames Wright { 7085037d55dSJames Wright CeedInt index = -1; 7095037d55dSJames Wright 7105037d55dSJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 7115037d55dSJames Wright if (ctx->mats_assembled_full[i] == mat_coo) index = i; 7125037d55dSJames Wright } 7135037d55dSJames Wright if (index == -1) PetscCall(MatCeedSetPreallocationCOO(mat_ceed, mat_coo)); 714c8564c30SJames Wright } 715c8564c30SJames Wright 716c8564c30SJames Wright // Assemble mat_ceed 71743327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 718c8564c30SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 719c8564c30SJames Wright { 720c8564c30SJames Wright const CeedScalar *values; 721c8564c30SJames Wright MatType mat_type; 722c8564c30SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 723c8564c30SJames Wright PetscBool is_spd, is_spd_known; 724c8564c30SJames Wright 725c8564c30SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 726c8564c30SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 727c8564c30SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 728c8564c30SJames Wright else mem_type = CEED_MEM_HOST; 729c8564c30SJames Wright 73043327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 73154831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemble(ctx->op_mult, ctx->coo_values_full)); 73243327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 73354831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_full, mem_type, &values)); 734c8564c30SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 735c8564c30SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 736c8564c30SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 73754831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_full, &values)); 738c8564c30SJames Wright } 739c8564c30SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 74043327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 741c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 742c8564c30SJames Wright } 743c8564c30SJames Wright 744c8564c30SJames Wright /** 7455037d55dSJames Wright @brief Set the current value of a context field for a `MatCEED`. 7465037d55dSJames Wright 7475037d55dSJames Wright Not collective across MPI processes. 7485037d55dSJames Wright 7495037d55dSJames Wright @param[in,out] mat `MatCEED` 7505037d55dSJames Wright @param[in] name Name of the context field 7515037d55dSJames Wright @param[in] value New context field value 7525037d55dSJames Wright 7535037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 7545037d55dSJames Wright **/ 7555037d55dSJames Wright PetscErrorCode MatCeedSetContextDouble(Mat mat, const char *name, double value) { 7565037d55dSJames Wright PetscBool was_updated = PETSC_FALSE; 7575037d55dSJames Wright MatCeedContext ctx; 7585037d55dSJames Wright 7595037d55dSJames Wright PetscFunctionBeginUser; 7605037d55dSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 7615037d55dSJames Wright { 7625037d55dSJames Wright CeedContextFieldLabel label = NULL; 7635037d55dSJames Wright 7645037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult, name, &label)); 7655037d55dSJames Wright if (label) { 766*243afec9SJames Wright double set_value = 2 * value + 1.0; 767*243afec9SJames Wright 768*243afec9SJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 769*243afec9SJames Wright if (set_value != value) { 7705037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult, label, &value)); 7715037d55dSJames Wright was_updated = PETSC_TRUE; 7725037d55dSJames Wright } 773*243afec9SJames Wright } 7745037d55dSJames Wright if (ctx->op_mult_transpose) { 7755037d55dSJames Wright label = NULL; 7765037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult_transpose, name, &label)); 7775037d55dSJames Wright if (label) { 778*243afec9SJames Wright double set_value = 2 * value + 1.0; 779*243afec9SJames Wright 780*243afec9SJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 781*243afec9SJames Wright if (set_value != value) { 7825037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult_transpose, label, &value)); 7835037d55dSJames Wright was_updated = PETSC_TRUE; 7845037d55dSJames Wright } 7855037d55dSJames Wright } 7865037d55dSJames Wright } 787*243afec9SJames Wright } 7885037d55dSJames Wright if (was_updated) { 7895037d55dSJames Wright PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 7905037d55dSJames Wright PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 7915037d55dSJames Wright } 7925037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 7935037d55dSJames Wright } 7945037d55dSJames Wright 7955037d55dSJames Wright /** 7965037d55dSJames Wright @brief Get the current value of a context field for a `MatCEED`. 7975037d55dSJames Wright 7985037d55dSJames Wright Not collective across MPI processes. 7995037d55dSJames Wright 8005037d55dSJames Wright @param[in] mat `MatCEED` 8015037d55dSJames Wright @param[in] name Name of the context field 8025037d55dSJames Wright @param[out] value Current context field value 8035037d55dSJames Wright 8045037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 8055037d55dSJames Wright **/ 8065037d55dSJames Wright PetscErrorCode MatCeedGetContextDouble(Mat mat, const char *name, double *value) { 8075037d55dSJames Wright MatCeedContext ctx; 8085037d55dSJames Wright 8095037d55dSJames Wright PetscFunctionBeginUser; 8105037d55dSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 8115037d55dSJames Wright { 8125037d55dSJames Wright CeedContextFieldLabel label = NULL; 8135037d55dSJames Wright CeedOperator op = ctx->op_mult; 8145037d55dSJames Wright 8155037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 8165037d55dSJames Wright if (!label && ctx->op_mult_transpose) { 8175037d55dSJames Wright op = ctx->op_mult_transpose; 8185037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 8195037d55dSJames Wright } 8205037d55dSJames Wright if (label) { 8215037d55dSJames Wright PetscSizeT num_values; 8225037d55dSJames Wright const double *values_ceed; 8235037d55dSJames Wright 8245037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextDoubleRead(op, label, &num_values, &values_ceed)); 8255037d55dSJames Wright *value = values_ceed[0]; 8265037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorRestoreContextDoubleRead(op, label, &values_ceed)); 8275037d55dSJames Wright } 8285037d55dSJames Wright } 8295037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 8305037d55dSJames Wright } 8315037d55dSJames Wright 8325037d55dSJames Wright /** 833*243afec9SJames Wright @brief Set the current `PetscReal` value of a context field for a `MatCEED`. 834*243afec9SJames Wright 835*243afec9SJames Wright Not collective across MPI processes. 836*243afec9SJames Wright 837*243afec9SJames Wright @param[in,out] mat `MatCEED` 838*243afec9SJames Wright @param[in] name Name of the context field 839*243afec9SJames Wright @param[in] value New context field value 840*243afec9SJames Wright 841*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 842*243afec9SJames Wright **/ 843*243afec9SJames Wright PetscErrorCode MatCeedSetContextReal(Mat mat, const char *name, PetscReal value) { 844*243afec9SJames Wright double value_double = value; 845*243afec9SJames Wright 846*243afec9SJames Wright PetscFunctionBeginUser; 847*243afec9SJames Wright PetscCall(MatCeedSetContextDouble(mat, name, value_double)); 848*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 849*243afec9SJames Wright } 850*243afec9SJames Wright 851*243afec9SJames Wright /** 852f965f5c6SJames Wright @brief Get the current `PetscReal` value of a context field for a `MatCEED`. 853f965f5c6SJames Wright 854f965f5c6SJames Wright Not collective across MPI processes. 855f965f5c6SJames Wright 856f965f5c6SJames Wright @param[in] mat `MatCEED` 857f965f5c6SJames Wright @param[in] name Name of the context field 858f965f5c6SJames Wright @param[out] value Current context field value 859f965f5c6SJames Wright 860f965f5c6SJames Wright @return An error code: 0 - success, otherwise - failure 861f965f5c6SJames Wright **/ 862f965f5c6SJames Wright PetscErrorCode MatCeedGetContextReal(Mat mat, const char *name, PetscReal *value) { 863*243afec9SJames Wright double value_double = 0.0; 864f965f5c6SJames Wright 865f965f5c6SJames Wright PetscFunctionBeginUser; 866f965f5c6SJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &value_double)); 867f965f5c6SJames Wright *value = value_double; 868f965f5c6SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 869f965f5c6SJames Wright } 870f965f5c6SJames Wright 871f965f5c6SJames Wright /** 872*243afec9SJames Wright @brief Set the current time for a `MatCEED`. 873*243afec9SJames Wright 874*243afec9SJames Wright Not collective across MPI processes. 875*243afec9SJames Wright 876*243afec9SJames Wright @param[in,out] mat `MatCEED` 877*243afec9SJames Wright @param[in] time Current time 878*243afec9SJames Wright 879*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 880*243afec9SJames Wright **/ 881*243afec9SJames Wright PetscErrorCode MatCeedSetTime(Mat mat, PetscReal time) { 882*243afec9SJames Wright PetscFunctionBeginUser; 883*243afec9SJames Wright { 884*243afec9SJames Wright double time_ceed = time; 885*243afec9SJames Wright 886*243afec9SJames Wright PetscCall(MatCeedSetContextDouble(mat, "time", time_ceed)); 887*243afec9SJames Wright } 888*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 889*243afec9SJames Wright } 890*243afec9SJames Wright 891*243afec9SJames Wright /** 892*243afec9SJames Wright @brief Get the current time for a `MatCEED`. 893*243afec9SJames Wright 894*243afec9SJames Wright Not collective across MPI processes. 895*243afec9SJames Wright 896*243afec9SJames Wright @param[in] mat `MatCEED` 897*243afec9SJames Wright @param[out] time Current time, or -1.0 if the boundary evaluator has no time field 898*243afec9SJames Wright 899*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 900*243afec9SJames Wright **/ 901*243afec9SJames Wright PetscErrorCode MatCeedGetTime(Mat mat, PetscReal *time) { 902*243afec9SJames Wright PetscFunctionBeginUser; 903*243afec9SJames Wright *time = -1.0; 904*243afec9SJames Wright { 905*243afec9SJames Wright double time_ceed = -1.0; 906*243afec9SJames Wright 907*243afec9SJames Wright PetscCall(MatCeedGetContextDouble(mat, "time", &time_ceed)); 908*243afec9SJames Wright *time = time_ceed; 909*243afec9SJames Wright } 910*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 911*243afec9SJames Wright } 912*243afec9SJames Wright 913*243afec9SJames Wright /** 914*243afec9SJames Wright @brief Set the current time step for a `MatCEED`. 915*243afec9SJames Wright 916*243afec9SJames Wright Not collective across MPI processes. 917*243afec9SJames Wright 918*243afec9SJames Wright @param[in,out] mat `MatCEED` 919*243afec9SJames Wright @param[in] dt Current time step 920*243afec9SJames Wright 921*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 922*243afec9SJames Wright **/ 923*243afec9SJames Wright PetscErrorCode MatCeedSetDt(Mat mat, PetscReal dt) { 924*243afec9SJames Wright PetscFunctionBeginUser; 925*243afec9SJames Wright { 926*243afec9SJames Wright double dt_ceed = dt; 927*243afec9SJames Wright 928*243afec9SJames Wright PetscCall(MatCeedSetContextDouble(mat, "dt", dt_ceed)); 929*243afec9SJames Wright } 930*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 931*243afec9SJames Wright } 932*243afec9SJames Wright 933*243afec9SJames Wright /** 934*243afec9SJames Wright @brief Set the Jacobian shifts for a `MatCEED`. 935*243afec9SJames Wright 936*243afec9SJames Wright Not collective across MPI processes. 937*243afec9SJames Wright 938*243afec9SJames Wright @param[in,out] mat `MatCEED` 939*243afec9SJames Wright @param[in] shift_v Velocity shift 940*243afec9SJames Wright @param[in] shift_a Acceleration shift 941*243afec9SJames Wright 942*243afec9SJames Wright @return An error code: 0 - success, otherwise - failure 943*243afec9SJames Wright **/ 944*243afec9SJames Wright PetscErrorCode MatCeedSetShifts(Mat mat, PetscReal shift_v, PetscReal shift_a) { 945*243afec9SJames Wright PetscFunctionBeginUser; 946*243afec9SJames Wright { 947*243afec9SJames Wright double shift_v_ceed = shift_v; 948*243afec9SJames Wright 949*243afec9SJames Wright PetscCall(MatCeedSetContextDouble(mat, "shift v", shift_v_ceed)); 950*243afec9SJames Wright } 951*243afec9SJames Wright if (shift_a) { 952*243afec9SJames Wright double shift_a_ceed = shift_a; 953*243afec9SJames Wright 954*243afec9SJames Wright PetscCall(MatCeedSetContextDouble(mat, "shift a", shift_a_ceed)); 955*243afec9SJames Wright } 956*243afec9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 957*243afec9SJames Wright } 958*243afec9SJames Wright 959*243afec9SJames Wright /** 960c8564c30SJames Wright @brief Set user context for a `MATCEED`. 961c8564c30SJames Wright 962c8564c30SJames Wright Collective across MPI processes. 963c8564c30SJames Wright 964c8564c30SJames Wright @param[in,out] mat `MATCEED` 965c8564c30SJames Wright @param[in] f The context destroy function, or NULL 966c8564c30SJames Wright @param[in] ctx User context, or NULL to unset 967c8564c30SJames Wright 968c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 969c8564c30SJames Wright **/ 970*243afec9SJames Wright PetscErrorCode MatCeedSetContext(Mat mat, PetscCtxDestroyFn f, void *ctx) { 971c8564c30SJames Wright PetscContainer user_ctx = NULL; 972c8564c30SJames Wright 973c8564c30SJames Wright PetscFunctionBeginUser; 974c8564c30SJames Wright if (ctx) { 975c8564c30SJames Wright PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)mat), &user_ctx)); 976c8564c30SJames Wright PetscCall(PetscContainerSetPointer(user_ctx, ctx)); 977*243afec9SJames Wright PetscCall(PetscContainerSetCtxDestroy(user_ctx, f)); 978c8564c30SJames Wright } 979c8564c30SJames Wright PetscCall(PetscObjectCompose((PetscObject)mat, "MatCeed user context", (PetscObject)user_ctx)); 980c8564c30SJames Wright PetscCall(PetscContainerDestroy(&user_ctx)); 981c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 982c8564c30SJames Wright } 983c8564c30SJames Wright 984c8564c30SJames Wright /** 985c8564c30SJames Wright @brief Retrieve the user context for a `MATCEED`. 986c8564c30SJames Wright 987c8564c30SJames Wright Collective across MPI processes. 988c8564c30SJames Wright 989c8564c30SJames Wright @param[in,out] mat `MATCEED` 990c8564c30SJames Wright @param[in] ctx User context 991c8564c30SJames Wright 992c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 993c8564c30SJames Wright **/ 994c8564c30SJames Wright PetscErrorCode MatCeedGetContext(Mat mat, void *ctx) { 995c8564c30SJames Wright PetscContainer user_ctx; 996c8564c30SJames Wright 997c8564c30SJames Wright PetscFunctionBeginUser; 998c8564c30SJames Wright PetscCall(PetscObjectQuery((PetscObject)mat, "MatCeed user context", (PetscObject *)&user_ctx)); 999c8564c30SJames Wright if (user_ctx) PetscCall(PetscContainerGetPointer(user_ctx, (void **)ctx)); 1000c8564c30SJames Wright else *(void **)ctx = NULL; 1001c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1002c8564c30SJames Wright } 1003c8564c30SJames Wright /** 10045037d55dSJames Wright @brief Set a user defined matrix operation for a `MATCEED` matrix. 10055037d55dSJames Wright 10065037d55dSJames Wright Within each user-defined routine, the user should call `MatCeedGetContext()` to obtain the user-defined context that was set by 10075037d55dSJames Wright `MatCeedSetContext()`. 1008c8564c30SJames Wright 1009c8564c30SJames Wright Collective across MPI processes. 1010c8564c30SJames Wright 1011c8564c30SJames Wright @param[in,out] mat `MATCEED` 10125037d55dSJames Wright @param[in] op Name of the `MatOperation` 10135037d55dSJames Wright @param[in] g Function that provides the operation 1014c8564c30SJames Wright 1015c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1016c8564c30SJames Wright **/ 10175037d55dSJames Wright PetscErrorCode MatCeedSetOperation(Mat mat, MatOperation op, void (*g)(void)) { 10185037d55dSJames Wright PetscFunctionBeginUser; 10195037d55dSJames Wright PetscCall(MatShellSetOperation(mat, op, g)); 10205037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 10215037d55dSJames Wright } 10225037d55dSJames Wright 10235037d55dSJames Wright /** 10245037d55dSJames Wright @brief Sets the default COO matrix type as a string from the `MATCEED`. 10255037d55dSJames Wright 10265037d55dSJames Wright Collective across MPI processes. 10275037d55dSJames Wright 10285037d55dSJames Wright @param[in,out] mat `MATCEED` 10295037d55dSJames Wright @param[in] type COO `MatType` to set 10305037d55dSJames Wright 10315037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 10325037d55dSJames Wright **/ 10335037d55dSJames Wright PetscErrorCode MatCeedSetCOOMatType(Mat mat, MatType type) { 1034c8564c30SJames Wright MatCeedContext ctx; 1035c8564c30SJames Wright 1036c8564c30SJames Wright PetscFunctionBeginUser; 1037c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1038c8564c30SJames Wright // Check if same 1039c8564c30SJames Wright { 1040c8564c30SJames Wright size_t len_old, len_new; 1041c8564c30SJames Wright PetscBool is_same = PETSC_FALSE; 1042c8564c30SJames Wright 10435037d55dSJames Wright PetscCall(PetscStrlen(ctx->coo_mat_type, &len_old)); 1044c8564c30SJames Wright PetscCall(PetscStrlen(type, &len_new)); 10455037d55dSJames Wright if (len_old == len_new) PetscCall(PetscStrncmp(ctx->coo_mat_type, type, len_old, &is_same)); 1046c8564c30SJames Wright if (is_same) PetscFunctionReturn(PETSC_SUCCESS); 1047c8564c30SJames Wright } 1048c8564c30SJames Wright // Clean up old mats in different format 1049c8564c30SJames Wright // LCOV_EXCL_START 1050c8564c30SJames Wright if (ctx->mat_assembled_full_internal) { 1051c8564c30SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 1052c8564c30SJames Wright if (ctx->mats_assembled_full[i] == ctx->mat_assembled_full_internal) { 1053c8564c30SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_full; j++) { 1054c8564c30SJames Wright ctx->mats_assembled_full[j - 1] = ctx->mats_assembled_full[j]; 1055c8564c30SJames Wright } 1056c8564c30SJames Wright ctx->num_mats_assembled_full--; 1057c8564c30SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 1058c8564c30SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 1059c8564c30SJames Wright } 1060c8564c30SJames Wright } 1061c8564c30SJames Wright } 1062c8564c30SJames Wright if (ctx->mat_assembled_pbd_internal) { 1063c8564c30SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 1064c8564c30SJames Wright if (ctx->mats_assembled_pbd[i] == ctx->mat_assembled_pbd_internal) { 1065c8564c30SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_pbd; j++) { 1066c8564c30SJames Wright ctx->mats_assembled_pbd[j - 1] = ctx->mats_assembled_pbd[j]; 1067c8564c30SJames Wright } 1068c8564c30SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 1069c8564c30SJames Wright ctx->num_mats_assembled_pbd--; 1070c8564c30SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 1071c8564c30SJames Wright } 1072c8564c30SJames Wright } 1073c8564c30SJames Wright } 10745037d55dSJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 10755037d55dSJames Wright PetscCall(PetscStrallocpy(type, &ctx->coo_mat_type)); 1076c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1077c8564c30SJames Wright // LCOV_EXCL_STOP 1078c8564c30SJames Wright } 1079c8564c30SJames Wright 1080c8564c30SJames Wright /** 10815037d55dSJames Wright @brief Gets the default COO matrix type as a string from the `MATCEED`. 1082c8564c30SJames Wright 1083c8564c30SJames Wright Collective across MPI processes. 1084c8564c30SJames Wright 1085c8564c30SJames Wright @param[in,out] mat `MATCEED` 10865037d55dSJames Wright @param[in] type COO `MatType` 1087c8564c30SJames Wright 1088c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1089c8564c30SJames Wright **/ 10905037d55dSJames Wright PetscErrorCode MatCeedGetCOOMatType(Mat mat, MatType *type) { 1091c8564c30SJames Wright MatCeedContext ctx; 1092c8564c30SJames Wright 1093c8564c30SJames Wright PetscFunctionBeginUser; 1094c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 10955037d55dSJames Wright *type = ctx->coo_mat_type; 1096c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1097c8564c30SJames Wright } 1098c8564c30SJames Wright 1099c8564c30SJames Wright /** 1100c8564c30SJames Wright @brief Set input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 1101c8564c30SJames Wright 1102c8564c30SJames Wright Not collective across MPI processes. 1103c8564c30SJames Wright 1104c8564c30SJames Wright @param[in,out] mat `MATCEED` 1105c8564c30SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 1106c8564c30SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 1107c8564c30SJames Wright 1108c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1109c8564c30SJames Wright **/ 1110c8564c30SJames Wright PetscErrorCode MatCeedSetLocalVectors(Mat mat, Vec X_loc, Vec Y_loc_transpose) { 1111c8564c30SJames Wright MatCeedContext ctx; 1112c8564c30SJames Wright 1113c8564c30SJames Wright PetscFunctionBeginUser; 1114c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1115c8564c30SJames Wright if (X_loc) { 1116c8564c30SJames Wright PetscInt len_old, len_new; 1117c8564c30SJames Wright 1118c8564c30SJames Wright PetscCall(VecGetSize(ctx->X_loc, &len_old)); 1119c8564c30SJames Wright PetscCall(VecGetSize(X_loc, &len_new)); 1120c8564c30SJames 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, 1121c8564c30SJames Wright len_new, len_old); 11225037d55dSJames Wright PetscCall(VecReferenceCopy(X_loc, &ctx->X_loc)); 1123c8564c30SJames Wright } 1124c8564c30SJames Wright if (Y_loc_transpose) { 1125c8564c30SJames Wright PetscInt len_old, len_new; 1126c8564c30SJames Wright 1127c8564c30SJames Wright PetscCall(VecGetSize(ctx->Y_loc_transpose, &len_old)); 1128c8564c30SJames Wright PetscCall(VecGetSize(Y_loc_transpose, &len_new)); 1129c8564c30SJames Wright PetscCheck(len_old == len_new, PETSC_COMM_SELF, PETSC_ERR_LIB, 1130c8564c30SJames Wright "new Y_loc_transpose length %" PetscInt_FMT " should match old Y_loc_transpose length %" PetscInt_FMT, len_new, len_old); 11315037d55dSJames Wright PetscCall(VecReferenceCopy(Y_loc_transpose, &ctx->Y_loc_transpose)); 1132c8564c30SJames Wright } 1133c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1134c8564c30SJames Wright } 1135c8564c30SJames Wright 1136c8564c30SJames Wright /** 1137c8564c30SJames Wright @brief Get input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 1138c8564c30SJames Wright 1139c8564c30SJames Wright Not collective across MPI processes. 1140c8564c30SJames Wright 1141c8564c30SJames Wright @param[in,out] mat `MATCEED` 1142c8564c30SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 1143c8564c30SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 1144c8564c30SJames Wright 1145c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1146c8564c30SJames Wright **/ 1147c8564c30SJames Wright PetscErrorCode MatCeedGetLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 1148c8564c30SJames Wright MatCeedContext ctx; 1149c8564c30SJames Wright 1150c8564c30SJames Wright PetscFunctionBeginUser; 1151c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1152c8564c30SJames Wright if (X_loc) { 11535037d55dSJames Wright *X_loc = NULL; 11545037d55dSJames Wright PetscCall(VecReferenceCopy(ctx->X_loc, X_loc)); 1155c8564c30SJames Wright } 1156c8564c30SJames Wright if (Y_loc_transpose) { 11575037d55dSJames Wright *Y_loc_transpose = NULL; 11585037d55dSJames Wright PetscCall(VecReferenceCopy(ctx->Y_loc_transpose, Y_loc_transpose)); 1159c8564c30SJames Wright } 1160c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1161c8564c30SJames Wright } 1162c8564c30SJames Wright 1163c8564c30SJames Wright /** 1164c8564c30SJames Wright @brief Restore input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 1165c8564c30SJames Wright 1166c8564c30SJames Wright Not collective across MPI processes. 1167c8564c30SJames Wright 1168c8564c30SJames Wright @param[in,out] mat MatCeed 1169c8564c30SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 1170c8564c30SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 1171c8564c30SJames Wright 1172c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1173c8564c30SJames Wright **/ 1174c8564c30SJames Wright PetscErrorCode MatCeedRestoreLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 1175c8564c30SJames Wright PetscFunctionBeginUser; 1176c8564c30SJames Wright if (X_loc) PetscCall(VecDestroy(X_loc)); 1177c8564c30SJames Wright if (Y_loc_transpose) PetscCall(VecDestroy(Y_loc_transpose)); 1178c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1179c8564c30SJames Wright } 1180c8564c30SJames Wright 1181c8564c30SJames Wright /** 1182c8564c30SJames Wright @brief Get libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 1183c8564c30SJames Wright 1184c8564c30SJames Wright Not collective across MPI processes. 1185c8564c30SJames Wright 1186c8564c30SJames Wright @param[in,out] mat MatCeed 1187c8564c30SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 1188c8564c30SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 1189c8564c30SJames Wright 1190c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1191c8564c30SJames Wright **/ 1192c8564c30SJames Wright PetscErrorCode MatCeedGetCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 1193c8564c30SJames Wright MatCeedContext ctx; 1194c8564c30SJames Wright 1195c8564c30SJames Wright PetscFunctionBeginUser; 1196c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1197c8564c30SJames Wright if (op_mult) { 1198c8564c30SJames Wright *op_mult = NULL; 119954831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult, op_mult)); 1200c8564c30SJames Wright } 1201c8564c30SJames Wright if (op_mult_transpose) { 1202c8564c30SJames Wright *op_mult_transpose = NULL; 120354831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult_transpose, op_mult_transpose)); 1204c8564c30SJames Wright } 1205c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1206c8564c30SJames Wright } 1207c8564c30SJames Wright 1208c8564c30SJames Wright /** 1209c8564c30SJames Wright @brief Restore libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 1210c8564c30SJames Wright 1211c8564c30SJames Wright Not collective across MPI processes. 1212c8564c30SJames Wright 1213c8564c30SJames Wright @param[in,out] mat MatCeed 1214c8564c30SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 1215c8564c30SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 1216c8564c30SJames Wright 1217c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1218c8564c30SJames Wright **/ 1219c8564c30SJames Wright PetscErrorCode MatCeedRestoreCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 1220c8564c30SJames Wright MatCeedContext ctx; 1221c8564c30SJames Wright 1222c8564c30SJames Wright PetscFunctionBeginUser; 1223c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 122454831c5fSJames Wright if (op_mult) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult)); 122554831c5fSJames Wright if (op_mult_transpose) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult_transpose)); 1226c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1227c8564c30SJames Wright } 1228c8564c30SJames Wright 1229c8564c30SJames Wright /** 1230c8564c30SJames Wright @brief Set `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1231c8564c30SJames Wright 1232c8564c30SJames Wright Not collective across MPI processes. 1233c8564c30SJames Wright 1234c8564c30SJames Wright @param[in,out] mat MatCeed 1235c8564c30SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 1236c8564c30SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 1237c8564c30SJames Wright 1238c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1239c8564c30SJames Wright **/ 1240c8564c30SJames Wright PetscErrorCode MatCeedSetLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 1241c8564c30SJames Wright MatCeedContext ctx; 1242c8564c30SJames Wright 1243c8564c30SJames Wright PetscFunctionBeginUser; 1244c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1245c8564c30SJames Wright if (log_event_mult) ctx->log_event_mult = log_event_mult; 1246c8564c30SJames Wright if (log_event_mult_transpose) ctx->log_event_mult_transpose = log_event_mult_transpose; 1247c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1248c8564c30SJames Wright } 1249c8564c30SJames Wright 1250c8564c30SJames Wright /** 1251c8564c30SJames Wright @brief Get `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1252c8564c30SJames Wright 1253c8564c30SJames Wright Not collective across MPI processes. 1254c8564c30SJames Wright 1255c8564c30SJames Wright @param[in,out] mat MatCeed 1256c8564c30SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 1257c8564c30SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 1258c8564c30SJames Wright 1259c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1260c8564c30SJames Wright **/ 1261c8564c30SJames Wright PetscErrorCode MatCeedGetLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 1262c8564c30SJames Wright MatCeedContext ctx; 1263c8564c30SJames Wright 1264c8564c30SJames Wright PetscFunctionBeginUser; 1265c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1266c8564c30SJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_mult; 1267c8564c30SJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_mult_transpose; 1268c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1269c8564c30SJames Wright } 1270c8564c30SJames Wright 127143327b86SJames Wright /** 127243327b86SJames Wright @brief Set `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 127343327b86SJames Wright 127443327b86SJames Wright Not collective across MPI processes. 127543327b86SJames Wright 127643327b86SJames Wright @param[in,out] mat MatCeed 127743327b86SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 127843327b86SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 127943327b86SJames Wright 128043327b86SJames Wright @return An error code: 0 - success, otherwise - failure 128143327b86SJames Wright **/ 128243327b86SJames Wright PetscErrorCode MatCeedSetCeedOperatorLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 128343327b86SJames Wright MatCeedContext ctx; 128443327b86SJames Wright 128543327b86SJames Wright PetscFunctionBeginUser; 128643327b86SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 128743327b86SJames Wright if (log_event_mult) ctx->log_event_ceed_mult = log_event_mult; 128843327b86SJames Wright if (log_event_mult_transpose) ctx->log_event_ceed_mult_transpose = log_event_mult_transpose; 128943327b86SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 129043327b86SJames Wright } 129143327b86SJames Wright 129243327b86SJames Wright /** 129343327b86SJames Wright @brief Get `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 129443327b86SJames Wright 129543327b86SJames Wright Not collective across MPI processes. 129643327b86SJames Wright 129743327b86SJames Wright @param[in,out] mat MatCeed 129843327b86SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 129943327b86SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 130043327b86SJames Wright 130143327b86SJames Wright @return An error code: 0 - success, otherwise - failure 130243327b86SJames Wright **/ 130343327b86SJames Wright PetscErrorCode MatCeedGetCeedOperatorLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 130443327b86SJames Wright MatCeedContext ctx; 130543327b86SJames Wright 130643327b86SJames Wright PetscFunctionBeginUser; 130743327b86SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 130843327b86SJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_ceed_mult; 130943327b86SJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_ceed_mult_transpose; 131043327b86SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 131143327b86SJames Wright } 131243327b86SJames Wright 1313c8564c30SJames Wright // ----------------------------------------------------------------------------- 1314c8564c30SJames Wright // Operator context data 1315c8564c30SJames Wright // ----------------------------------------------------------------------------- 1316c8564c30SJames Wright 1317c8564c30SJames Wright /** 1318c8564c30SJames Wright @brief Setup context data for operator application. 1319c8564c30SJames Wright 1320c8564c30SJames Wright Collective across MPI processes. 1321c8564c30SJames Wright 1322c8564c30SJames Wright @param[in] dm_x Input `DM` 1323c8564c30SJames Wright @param[in] dm_y Output `DM` 1324c8564c30SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 1325c8564c30SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 1326c8564c30SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 1327c8564c30SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 1328c8564c30SJames Wright @param[in] log_event_mult `PetscLogEvent` for forward evaluation 1329c8564c30SJames Wright @param[in] log_event_mult_transpose `PetscLogEvent` for transpose evaluation 133043327b86SJames Wright @param[in] log_event_ceed_mult `PetscLogEvent` for forward `CeedOperator` evaluation 133143327b86SJames Wright @param[in] log_event_ceed_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation 1332c8564c30SJames Wright @param[out] ctx Context data for operator evaluation 1333c8564c30SJames Wright 1334c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1335c8564c30SJames Wright **/ 1336c8564c30SJames Wright PetscErrorCode MatCeedContextCreate(DM dm_x, DM dm_y, Vec X_loc, Vec Y_loc_transpose, CeedOperator op_mult, CeedOperator op_mult_transpose, 133743327b86SJames Wright PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose, PetscLogEvent log_event_ceed_mult, 133843327b86SJames Wright PetscLogEvent log_event_ceed_mult_transpose, MatCeedContext *ctx) { 1339c8564c30SJames Wright CeedSize x_loc_len, y_loc_len; 1340c8564c30SJames Wright 1341c8564c30SJames Wright PetscFunctionBeginUser; 1342c8564c30SJames Wright 1343c8564c30SJames Wright // Allocate 1344c8564c30SJames Wright PetscCall(PetscNew(ctx)); 1345c8564c30SJames Wright (*ctx)->ref_count = 1; 1346c8564c30SJames Wright 1347c8564c30SJames Wright // Logging 1348c8564c30SJames Wright (*ctx)->log_event_mult = log_event_mult; 1349c8564c30SJames Wright (*ctx)->log_event_mult_transpose = log_event_mult_transpose; 135043327b86SJames Wright (*ctx)->log_event_ceed_mult = log_event_ceed_mult; 135143327b86SJames Wright (*ctx)->log_event_ceed_mult_transpose = log_event_ceed_mult_transpose; 1352c8564c30SJames Wright 1353c8564c30SJames Wright // PETSc objects 13545037d55dSJames Wright PetscCall(DMReferenceCopy(dm_x, &(*ctx)->dm_x)); 13555037d55dSJames Wright PetscCall(DMReferenceCopy(dm_y, &(*ctx)->dm_y)); 13565037d55dSJames Wright if (X_loc) PetscCall(VecReferenceCopy(X_loc, &(*ctx)->X_loc)); 13575037d55dSJames Wright if (Y_loc_transpose) PetscCall(VecReferenceCopy(Y_loc_transpose, &(*ctx)->Y_loc_transpose)); 1358c8564c30SJames Wright 1359c8564c30SJames Wright // Memtype 1360c8564c30SJames Wright { 1361c8564c30SJames Wright const PetscScalar *x; 1362c8564c30SJames Wright Vec X; 1363c8564c30SJames Wright 1364c8564c30SJames Wright PetscCall(DMGetLocalVector(dm_x, &X)); 1365c8564c30SJames Wright PetscCall(VecGetArrayReadAndMemType(X, &x, &(*ctx)->mem_type)); 1366c8564c30SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X, &x)); 1367c8564c30SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &X)); 1368c8564c30SJames Wright } 1369c8564c30SJames Wright 1370c8564c30SJames Wright // libCEED objects 1371c8564c30SJames Wright PetscCheck(CeedOperatorGetCeed(op_mult, &(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, 1372c8564c30SJames Wright "retrieving Ceed context object failed"); 137354831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedReference((*ctx)->ceed)); 137454831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetActiveVectorLengths(op_mult, &x_loc_len, &y_loc_len)); 137554831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult, &(*ctx)->op_mult)); 137654831c5fSJames Wright if (op_mult_transpose) PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult_transpose, &(*ctx)->op_mult_transpose)); 137754831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, x_loc_len, &(*ctx)->x_loc)); 137854831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, y_loc_len, &(*ctx)->y_loc)); 1379c8564c30SJames Wright 1380c8564c30SJames Wright // Flop counting 1381c8564c30SJames Wright { 1382c8564c30SJames Wright CeedSize ceed_flops_estimate = 0; 1383c8564c30SJames Wright 138454831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult, &ceed_flops_estimate)); 1385c8564c30SJames Wright (*ctx)->flops_mult = ceed_flops_estimate; 1386c8564c30SJames Wright if (op_mult_transpose) { 138754831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult_transpose, &ceed_flops_estimate)); 1388c8564c30SJames Wright (*ctx)->flops_mult_transpose = ceed_flops_estimate; 1389c8564c30SJames Wright } 1390c8564c30SJames Wright } 1391c8564c30SJames Wright 1392c8564c30SJames Wright // Check sizes 1393c8564c30SJames Wright if (x_loc_len > 0 || y_loc_len > 0) { 1394c8564c30SJames Wright CeedSize ctx_x_loc_len, ctx_y_loc_len; 1395c8564c30SJames Wright PetscInt X_loc_len, dm_x_loc_len, Y_loc_len, dm_y_loc_len; 1396c8564c30SJames Wright Vec dm_X_loc, dm_Y_loc; 1397c8564c30SJames Wright 1398c8564c30SJames Wright // -- Input 1399c8564c30SJames Wright PetscCall(DMGetLocalVector(dm_x, &dm_X_loc)); 1400c8564c30SJames Wright PetscCall(VecGetLocalSize(dm_X_loc, &dm_x_loc_len)); 1401c8564c30SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &dm_X_loc)); 140254831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->x_loc, &ctx_x_loc_len)); 1403c86b9822SJames Wright if (X_loc) { 1404c86b9822SJames Wright PetscCall(VecGetLocalSize(X_loc, &X_loc_len)); 1405c86b9822SJames Wright PetscCheck(X_loc_len == dm_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 1406c86b9822SJames Wright "X_loc (%" PetscInt_FMT ") must match dm_x (%" PetscInt_FMT ") dimensions", X_loc_len, dm_x_loc_len); 1407c86b9822SJames Wright } 1408c86b9822SJames 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", 1409c86b9822SJames Wright x_loc_len, dm_x_loc_len); 1410c86b9822SJames 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 ")", 1411c86b9822SJames Wright x_loc_len, ctx_x_loc_len); 1412c8564c30SJames Wright 1413c8564c30SJames Wright // -- Output 1414c8564c30SJames Wright PetscCall(DMGetLocalVector(dm_y, &dm_Y_loc)); 1415c8564c30SJames Wright PetscCall(VecGetLocalSize(dm_Y_loc, &dm_y_loc_len)); 1416c8564c30SJames Wright PetscCall(DMRestoreLocalVector(dm_y, &dm_Y_loc)); 141754831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->y_loc, &ctx_y_loc_len)); 1418c86b9822SJames 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", 1419c86b9822SJames Wright ctx_y_loc_len, dm_y_loc_len); 1420c8564c30SJames Wright 1421c8564c30SJames Wright // -- Transpose 1422c8564c30SJames Wright if (Y_loc_transpose) { 1423c8564c30SJames Wright PetscCall(VecGetLocalSize(Y_loc_transpose, &Y_loc_len)); 1424c86b9822SJames Wright PetscCheck(Y_loc_len == dm_y_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 1425c86b9822SJames Wright "Y_loc_transpose (%" PetscInt_FMT ") must match dm_y (%" PetscInt_FMT ") dimensions", Y_loc_len, dm_y_loc_len); 1426c8564c30SJames Wright } 1427c8564c30SJames Wright } 1428c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1429c8564c30SJames Wright } 1430c8564c30SJames Wright 1431c8564c30SJames Wright /** 1432c8564c30SJames Wright @brief Increment reference counter for `MATCEED` context. 1433c8564c30SJames Wright 1434c8564c30SJames Wright Not collective across MPI processes. 1435c8564c30SJames Wright 1436c8564c30SJames Wright @param[in,out] ctx Context data 1437c8564c30SJames Wright 1438c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1439c8564c30SJames Wright **/ 1440c8564c30SJames Wright PetscErrorCode MatCeedContextReference(MatCeedContext ctx) { 1441c8564c30SJames Wright PetscFunctionBeginUser; 1442c8564c30SJames Wright ctx->ref_count++; 1443c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1444c8564c30SJames Wright } 1445c8564c30SJames Wright 1446c8564c30SJames Wright /** 1447c8564c30SJames Wright @brief Copy reference for `MATCEED`. 1448c8564c30SJames Wright Note: If `ctx_copy` is non-null, it is assumed to be a valid pointer to a `MatCeedContext`. 1449c8564c30SJames Wright 1450c8564c30SJames Wright Not collective across MPI processes. 1451c8564c30SJames Wright 1452c8564c30SJames Wright @param[in] ctx Context data 1453c8564c30SJames Wright @param[out] ctx_copy Copy of pointer to context data 1454c8564c30SJames Wright 1455c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1456c8564c30SJames Wright **/ 1457c8564c30SJames Wright PetscErrorCode MatCeedContextReferenceCopy(MatCeedContext ctx, MatCeedContext *ctx_copy) { 1458c8564c30SJames Wright PetscFunctionBeginUser; 1459c8564c30SJames Wright PetscCall(MatCeedContextReference(ctx)); 1460*243afec9SJames Wright PetscCall(MatCeedContextDestroy(ctx_copy)); 1461c8564c30SJames Wright *ctx_copy = ctx; 1462c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1463c8564c30SJames Wright } 1464c8564c30SJames Wright 1465c8564c30SJames Wright /** 1466c8564c30SJames Wright @brief Destroy context data for operator application. 1467c8564c30SJames Wright 1468c8564c30SJames Wright Collective across MPI processes. 1469c8564c30SJames Wright 1470c8564c30SJames Wright @param[in,out] ctx Context data for operator evaluation 1471c8564c30SJames Wright 1472c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1473c8564c30SJames Wright **/ 1474*243afec9SJames Wright PetscErrorCode MatCeedContextDestroy(MatCeedContext *ctx) { 1475c8564c30SJames Wright PetscFunctionBeginUser; 1476*243afec9SJames Wright if (!ctx || --(*ctx)->ref_count > 0) PetscFunctionReturn(PETSC_SUCCESS); 1477c8564c30SJames Wright 1478c8564c30SJames Wright // PETSc objects 1479*243afec9SJames Wright PetscCall(DMDestroy(&(*ctx)->dm_x)); 1480*243afec9SJames Wright PetscCall(DMDestroy(&(*ctx)->dm_y)); 1481*243afec9SJames Wright PetscCall(VecDestroy(&(*ctx)->X_loc)); 1482*243afec9SJames Wright PetscCall(VecDestroy(&(*ctx)->Y_loc_transpose)); 1483*243afec9SJames Wright PetscCall(MatDestroy(&(*ctx)->mat_assembled_full_internal)); 1484*243afec9SJames Wright PetscCall(MatDestroy(&(*ctx)->mat_assembled_pbd_internal)); 1485*243afec9SJames Wright PetscCall(PetscFree((*ctx)->coo_mat_type)); 1486*243afec9SJames Wright PetscCall(PetscFree((*ctx)->mats_assembled_full)); 1487*243afec9SJames Wright PetscCall(PetscFree((*ctx)->mats_assembled_pbd)); 1488c8564c30SJames Wright 1489c8564c30SJames Wright // libCEED objects 1490*243afec9SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->x_loc)); 1491*243afec9SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->y_loc)); 1492*243afec9SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->coo_values_full)); 1493*243afec9SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->coo_values_pbd)); 1494*243afec9SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorDestroy(&(*ctx)->op_mult)); 1495*243afec9SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorDestroy(&(*ctx)->op_mult_transpose)); 1496*243afec9SJames Wright PetscCheck(CeedDestroy(&(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, "destroying libCEED context object failed"); 1497c8564c30SJames Wright 1498c8564c30SJames Wright // Deallocate 1499*243afec9SJames Wright (*ctx)->is_destroyed = PETSC_TRUE; // Flag as destroyed in case someone has stale ref 1500*243afec9SJames Wright PetscCall(PetscFree(*ctx)); 1501c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1502c8564c30SJames Wright } 1503c8564c30SJames Wright 1504c8564c30SJames Wright /** 1505c8564c30SJames Wright @brief Compute the diagonal of an operator via libCEED. 1506c8564c30SJames Wright 1507c8564c30SJames Wright Collective across MPI processes. 1508c8564c30SJames Wright 1509c8564c30SJames Wright @param[in] A `MATCEED` 1510c8564c30SJames Wright @param[out] D Vector holding operator diagonal 1511c8564c30SJames Wright 1512c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1513c8564c30SJames Wright **/ 1514c8564c30SJames Wright PetscErrorCode MatGetDiagonal_Ceed(Mat A, Vec D) { 1515c8564c30SJames Wright PetscMemType mem_type; 1516c8564c30SJames Wright Vec D_loc; 1517c8564c30SJames Wright MatCeedContext ctx; 1518c8564c30SJames Wright 1519c8564c30SJames Wright PetscFunctionBeginUser; 1520c8564c30SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1521c8564c30SJames Wright 1522c8564c30SJames Wright // Place PETSc vector in libCEED vector 152343327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 1524c8564c30SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &D_loc)); 1525d0593705SJames Wright PetscCall(VecPetscToCeed(D_loc, &mem_type, ctx->x_loc)); 1526c8564c30SJames Wright 1527c8564c30SJames Wright // Compute Diagonal 152843327b86SJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 152954831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleDiagonal(ctx->op_mult, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 153043327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 1531c8564c30SJames Wright 1532c8564c30SJames Wright // Restore PETSc vector 1533d0593705SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, mem_type, D_loc)); 1534c8564c30SJames Wright 1535c8564c30SJames Wright // Local-to-Global 1536c8564c30SJames Wright PetscCall(VecZeroEntries(D)); 1537c8564c30SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, D_loc, ADD_VALUES, D)); 1538c8564c30SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &D_loc)); 153943327b86SJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 1540c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1541c8564c30SJames Wright } 1542c8564c30SJames Wright 1543c8564c30SJames Wright /** 1544c8564c30SJames Wright @brief Compute `A X = Y` for a `MATCEED`. 1545c8564c30SJames Wright 1546c8564c30SJames Wright Collective across MPI processes. 1547c8564c30SJames Wright 1548c8564c30SJames Wright @param[in] A `MATCEED` 1549c8564c30SJames Wright @param[in] X Input PETSc vector 1550c8564c30SJames Wright @param[out] Y Output PETSc vector 1551c8564c30SJames Wright 1552c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1553c8564c30SJames Wright **/ 1554c8564c30SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 1555c8564c30SJames Wright MatCeedContext ctx; 1556c8564c30SJames Wright 1557c8564c30SJames Wright PetscFunctionBeginUser; 1558c8564c30SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 155943327b86SJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult, A, X, Y, NULL)); 1560c8564c30SJames Wright 1561c8564c30SJames Wright { 1562c8564c30SJames Wright PetscMemType x_mem_type, y_mem_type; 1563c8564c30SJames Wright Vec X_loc = ctx->X_loc, Y_loc; 1564c8564c30SJames Wright 1565c8564c30SJames Wright // Get local vectors 1566c8564c30SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 1567c8564c30SJames Wright PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 1568c8564c30SJames Wright 1569c8564c30SJames Wright // Global-to-local 1570c8564c30SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc)); 1571c8564c30SJames Wright 1572c8564c30SJames Wright // Setup libCEED vectors 1573d0593705SJames Wright PetscCall(VecReadPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 1574c8564c30SJames Wright PetscCall(VecZeroEntries(Y_loc)); 1575d0593705SJames Wright PetscCall(VecPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 1576c8564c30SJames Wright 1577c8564c30SJames Wright // Apply libCEED operator 157843327b86SJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult, A, X, Y, NULL)); 1579*243afec9SJames Wright PetscCall(PetscLogGpuTimeBegin()); 158054831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult, ctx->x_loc, ctx->y_loc, CEED_REQUEST_IMMEDIATE)); 1581c8564c30SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1582*243afec9SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult, A, X, Y, NULL)); 1583c8564c30SJames Wright 1584c8564c30SJames Wright // Restore PETSc vectors 1585d0593705SJames Wright PetscCall(VecReadCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1586d0593705SJames Wright PetscCall(VecCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1587c8564c30SJames Wright 1588c8564c30SJames Wright // Local-to-global 1589c8564c30SJames Wright PetscCall(VecZeroEntries(Y)); 1590c8564c30SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y)); 1591c8564c30SJames Wright 1592c8564c30SJames Wright // Restore local vectors, as needed 1593c8564c30SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 1594c8564c30SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 1595c8564c30SJames Wright } 1596c8564c30SJames Wright 1597c8564c30SJames Wright // Log flops 1598c8564c30SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult)); 1599c8564c30SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult)); 160043327b86SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult, A, X, Y, NULL)); 1601c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1602c8564c30SJames Wright } 1603c8564c30SJames Wright 1604c8564c30SJames Wright /** 1605c8564c30SJames Wright @brief Compute `A^T Y = X` for a `MATCEED`. 1606c8564c30SJames Wright 1607c8564c30SJames Wright Collective across MPI processes. 1608c8564c30SJames Wright 1609c8564c30SJames Wright @param[in] A `MATCEED` 1610c8564c30SJames Wright @param[in] Y Input PETSc vector 1611c8564c30SJames Wright @param[out] X Output PETSc vector 1612c8564c30SJames Wright 1613c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1614c8564c30SJames Wright **/ 1615c8564c30SJames Wright PetscErrorCode MatMultTranspose_Ceed(Mat A, Vec Y, Vec X) { 1616c8564c30SJames Wright MatCeedContext ctx; 1617c8564c30SJames Wright 1618c8564c30SJames Wright PetscFunctionBeginUser; 1619c8564c30SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 162043327b86SJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult_transpose, A, Y, X, NULL)); 1621c8564c30SJames Wright 1622c8564c30SJames Wright { 1623c8564c30SJames Wright PetscMemType x_mem_type, y_mem_type; 1624c8564c30SJames Wright Vec X_loc, Y_loc = ctx->Y_loc_transpose; 1625c8564c30SJames Wright 1626c8564c30SJames Wright // Get local vectors 1627c8564c30SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 1628c8564c30SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 1629c8564c30SJames Wright 1630c8564c30SJames Wright // Global-to-local 1631c8564c30SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_y, Y, INSERT_VALUES, Y_loc)); 1632c8564c30SJames Wright 1633c8564c30SJames Wright // Setup libCEED vectors 1634d0593705SJames Wright PetscCall(VecReadPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 1635c8564c30SJames Wright PetscCall(VecZeroEntries(X_loc)); 1636d0593705SJames Wright PetscCall(VecPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 1637c8564c30SJames Wright 1638c8564c30SJames Wright // Apply libCEED operator 163943327b86SJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 1640*243afec9SJames Wright PetscCall(PetscLogGpuTimeBegin()); 164154831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult_transpose, ctx->y_loc, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1642c8564c30SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1643*243afec9SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 1644c8564c30SJames Wright 1645c8564c30SJames Wright // Restore PETSc vectors 1646d0593705SJames Wright PetscCall(VecReadCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1647d0593705SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1648c8564c30SJames Wright 1649c8564c30SJames Wright // Local-to-global 1650c8564c30SJames Wright PetscCall(VecZeroEntries(X)); 1651c8564c30SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, X_loc, ADD_VALUES, X)); 1652c8564c30SJames Wright 1653c8564c30SJames Wright // Restore local vectors, as needed 1654c8564c30SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 1655c8564c30SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 1656c8564c30SJames Wright } 1657c8564c30SJames Wright 1658c8564c30SJames Wright // Log flops 1659c8564c30SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult_transpose)); 1660c8564c30SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult_transpose)); 166143327b86SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult_transpose, A, Y, X, NULL)); 1662c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1663c8564c30SJames Wright } 1664