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> 10c8564c30SJames Wright #include <petscdmplex.h> 11c8564c30SJames Wright #include <stdlib.h> 12c8564c30SJames Wright #include <string.h> 13c8564c30SJames Wright 14c8564c30SJames Wright PetscClassId MATCEED_CLASSID; 15c8564c30SJames Wright PetscLogEvent MATCEED_MULT, MATCEED_MULT_TRANSPOSE; 16c8564c30SJames Wright 17c8564c30SJames Wright /** 18c8564c30SJames Wright @brief Register MATCEED log events. 19c8564c30SJames Wright 20c8564c30SJames Wright Not collective across MPI processes. 21c8564c30SJames Wright 22c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 23c8564c30SJames Wright **/ 24c8564c30SJames Wright static PetscErrorCode MatCeedRegisterLogEvents() { 255037d55dSJames Wright static PetscBool registered = PETSC_FALSE; 26c8564c30SJames Wright 27c8564c30SJames Wright PetscFunctionBeginUser; 28c8564c30SJames Wright if (registered) PetscFunctionReturn(PETSC_SUCCESS); 29c8564c30SJames Wright PetscCall(PetscClassIdRegister("MATCEED", &MATCEED_CLASSID)); 30c8564c30SJames Wright PetscCall(PetscLogEventRegister("MATCEED Mult", MATCEED_CLASSID, &MATCEED_MULT)); 31c8564c30SJames Wright PetscCall(PetscLogEventRegister("MATCEED Mult Transpose", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE)); 325037d55dSJames Wright registered = PETSC_TRUE; 33c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 34c8564c30SJames Wright } 35c8564c30SJames Wright 36c8564c30SJames Wright /** 37c8564c30SJames Wright @brief Assemble the point block diagonal of a `MATCEED` into a `MATAIJ` or similar. 38c8564c30SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 39c8564c30SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 40c8564c30SJames Wright 41c8564c30SJames Wright Collective across MPI processes. 42c8564c30SJames Wright 43c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to assemble 44c8564c30SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 45c8564c30SJames Wright 46c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 47c8564c30SJames Wright **/ 48c8564c30SJames Wright static PetscErrorCode MatCeedAssemblePointBlockDiagonalCOO(Mat mat_ceed, Mat mat_coo) { 49c8564c30SJames Wright MatCeedContext ctx; 50c8564c30SJames Wright 51c8564c30SJames Wright PetscFunctionBeginUser; 52c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 53c8564c30SJames Wright 54c8564c30SJames Wright // Check if COO pattern set 55c8564c30SJames Wright { 56c8564c30SJames Wright PetscInt index = -1; 57c8564c30SJames Wright 58c8564c30SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 59c8564c30SJames Wright if (ctx->mats_assembled_pbd[i] == mat_coo) index = i; 60c8564c30SJames Wright } 61c8564c30SJames Wright if (index == -1) { 62c8564c30SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 63c8564c30SJames Wright CeedInt *rows_ceed, *cols_ceed; 64c8564c30SJames Wright PetscCount num_entries; 65c8564c30SJames Wright PetscLogStage stage_amg_setup; 66c8564c30SJames Wright 67c8564c30SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 68c8564c30SJames Wright PetscCall(PetscLogStageGetId("MATCEED Assembly Setup", &stage_amg_setup)); 69c8564c30SJames Wright if (stage_amg_setup == -1) { 70c8564c30SJames Wright PetscCall(PetscLogStageRegister("MATCEED Assembly Setup", &stage_amg_setup)); 71c8564c30SJames Wright } 72c8564c30SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 7354831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonalSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 74d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 75d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 76c8564c30SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 77c8564c30SJames Wright free(rows_petsc); 78c8564c30SJames Wright free(cols_petsc); 7954831c5fSJames Wright if (!ctx->coo_values_pbd) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_pbd)); 80c8564c30SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_pbd * sizeof(Mat), &ctx->mats_assembled_pbd)); 81c8564c30SJames Wright ctx->mats_assembled_pbd[ctx->num_mats_assembled_pbd - 1] = mat_coo; 82c8564c30SJames Wright PetscCall(PetscLogStagePop()); 83c8564c30SJames Wright } 84c8564c30SJames Wright } 85c8564c30SJames Wright 86c8564c30SJames Wright // Assemble mat_ceed 87c8564c30SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 88c8564c30SJames Wright { 89c8564c30SJames Wright const CeedScalar *values; 90c8564c30SJames Wright MatType mat_type; 91c8564c30SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 92c8564c30SJames Wright PetscBool is_spd, is_spd_known; 93c8564c30SJames Wright 94c8564c30SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 95c8564c30SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 96c8564c30SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 97c8564c30SJames Wright else mem_type = CEED_MEM_HOST; 98c8564c30SJames Wright 9954831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonal(ctx->op_mult, ctx->coo_values_pbd, CEED_REQUEST_IMMEDIATE)); 10054831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_pbd, mem_type, &values)); 101c8564c30SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 102c8564c30SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 103c8564c30SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 10454831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_pbd, &values)); 105c8564c30SJames Wright } 106c8564c30SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 107c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 108c8564c30SJames Wright } 109c8564c30SJames Wright 110c8564c30SJames Wright /** 111c8564c30SJames Wright @brief Assemble inner `Mat` for diagonal `PC` operations 112c8564c30SJames Wright 113c8564c30SJames Wright Collective across MPI processes. 114c8564c30SJames Wright 115c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to invert 116c8564c30SJames Wright @param[in] use_ceed_pbd Boolean flag to use libCEED PBD assembly 117c8564c30SJames Wright @param[out] mat_inner Inner `Mat` for diagonal operations 118c8564c30SJames Wright 119c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 120c8564c30SJames Wright **/ 121c8564c30SJames Wright static PetscErrorCode MatCeedAssembleInnerBlockDiagonalMat(Mat mat_ceed, PetscBool use_ceed_pbd, Mat *mat_inner) { 122c8564c30SJames Wright MatCeedContext ctx; 123c8564c30SJames Wright 124c8564c30SJames Wright PetscFunctionBeginUser; 125c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 126c8564c30SJames Wright if (use_ceed_pbd) { 127c8564c30SJames Wright // Check if COO pattern set 1285037d55dSJames Wright if (!ctx->mat_assembled_pbd_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_pbd_internal)); 129c8564c30SJames Wright 130c8564c30SJames Wright // Assemble mat_assembled_full_internal 131c8564c30SJames Wright PetscCall(MatCeedAssemblePointBlockDiagonalCOO(mat_ceed, ctx->mat_assembled_pbd_internal)); 132c8564c30SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_pbd_internal; 133c8564c30SJames Wright } else { 134c8564c30SJames Wright // Check if COO pattern set 1355037d55dSJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 136c8564c30SJames Wright 137c8564c30SJames Wright // Assemble mat_assembled_full_internal 138c8564c30SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 139c8564c30SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_full_internal; 140c8564c30SJames Wright } 141c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 142c8564c30SJames Wright } 143c8564c30SJames Wright 144c8564c30SJames Wright /** 145c8564c30SJames Wright @brief Get `MATCEED` diagonal block for Jacobi. 146c8564c30SJames Wright 147c8564c30SJames Wright Collective across MPI processes. 148c8564c30SJames Wright 149c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to invert 150c8564c30SJames Wright @param[out] mat_block The diagonal block matrix 151c8564c30SJames Wright 152c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 153c8564c30SJames Wright **/ 154c8564c30SJames Wright static PetscErrorCode MatGetDiagonalBlock_Ceed(Mat mat_ceed, Mat *mat_block) { 155c8564c30SJames Wright Mat mat_inner = NULL; 156c8564c30SJames Wright MatCeedContext ctx; 157c8564c30SJames Wright 158c8564c30SJames Wright PetscFunctionBeginUser; 159c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 160c8564c30SJames Wright 161c8564c30SJames Wright // Assemble inner mat if needed 162c8564c30SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_pbd_valid, &mat_inner)); 163c8564c30SJames Wright 164c8564c30SJames Wright // Get block diagonal 165c8564c30SJames Wright PetscCall(MatGetDiagonalBlock(mat_inner, mat_block)); 166c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 167c8564c30SJames Wright } 168c8564c30SJames Wright 169c8564c30SJames Wright /** 170c8564c30SJames Wright @brief Invert `MATCEED` diagonal block for Jacobi. 171c8564c30SJames Wright 172c8564c30SJames Wright Collective across MPI processes. 173c8564c30SJames Wright 174c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to invert 175c8564c30SJames Wright @param[out] values The block inverses in column major order 176c8564c30SJames Wright 177c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 178c8564c30SJames Wright **/ 179c8564c30SJames Wright static PetscErrorCode MatInvertBlockDiagonal_Ceed(Mat mat_ceed, const PetscScalar **values) { 180c8564c30SJames Wright Mat mat_inner = NULL; 181c8564c30SJames Wright MatCeedContext ctx; 182c8564c30SJames Wright 183c8564c30SJames Wright PetscFunctionBeginUser; 184c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 185c8564c30SJames Wright 186c8564c30SJames Wright // Assemble inner mat if needed 187c8564c30SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_pbd_valid, &mat_inner)); 188c8564c30SJames Wright 189c8564c30SJames Wright // Invert PB diagonal 190c8564c30SJames Wright PetscCall(MatInvertBlockDiagonal(mat_inner, values)); 191c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 192c8564c30SJames Wright } 193c8564c30SJames Wright 194c8564c30SJames Wright /** 195c8564c30SJames Wright @brief Invert `MATCEED` variable diagonal block for Jacobi. 196c8564c30SJames Wright 197c8564c30SJames Wright Collective across MPI processes. 198c8564c30SJames Wright 199c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to invert 200c8564c30SJames Wright @param[in] num_blocks The number of blocks on the process 201c8564c30SJames Wright @param[in] block_sizes The size of each block on the process 202c8564c30SJames Wright @param[out] values The block inverses in column major order 203c8564c30SJames Wright 204c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 205c8564c30SJames Wright **/ 206c8564c30SJames Wright static PetscErrorCode MatInvertVariableBlockDiagonal_Ceed(Mat mat_ceed, PetscInt num_blocks, const PetscInt *block_sizes, PetscScalar *values) { 207c8564c30SJames Wright Mat mat_inner = NULL; 208c8564c30SJames Wright MatCeedContext ctx; 209c8564c30SJames Wright 210c8564c30SJames Wright PetscFunctionBeginUser; 211c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 212c8564c30SJames Wright 213c8564c30SJames Wright // Assemble inner mat if needed 214c8564c30SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_vpbd_valid, &mat_inner)); 215c8564c30SJames Wright 216c8564c30SJames Wright // Invert PB diagonal 217c8564c30SJames Wright PetscCall(MatInvertVariableBlockDiagonal(mat_inner, num_blocks, block_sizes, values)); 218c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 219c8564c30SJames Wright } 220c8564c30SJames Wright 2213933d9a0SJames Wright /** 2223933d9a0SJames Wright @brief View `MATCEED`. 2233933d9a0SJames Wright 2243933d9a0SJames Wright Collective across MPI processes. 2253933d9a0SJames Wright 2263933d9a0SJames Wright @param[in] mat_ceed `MATCEED` to view 2273933d9a0SJames Wright @param[in] viewer The visualization context 2283933d9a0SJames Wright 2293933d9a0SJames Wright @return An error code: 0 - success, otherwise - failure 2303933d9a0SJames Wright **/ 2313933d9a0SJames Wright static PetscErrorCode MatView_Ceed(Mat mat_ceed, PetscViewer viewer) { 2323933d9a0SJames Wright PetscBool is_ascii; 2333933d9a0SJames Wright PetscViewerFormat format; 2343933d9a0SJames Wright PetscMPIInt size; 2353933d9a0SJames Wright MatCeedContext ctx; 2363933d9a0SJames Wright 2373933d9a0SJames Wright PetscFunctionBeginUser; 2383933d9a0SJames Wright PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2393933d9a0SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 2403933d9a0SJames Wright if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat_ceed), &viewer)); 2413933d9a0SJames Wright 2423933d9a0SJames Wright PetscCall(PetscViewerGetFormat(viewer, &format)); 2433933d9a0SJames Wright PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat_ceed), &size)); 2443933d9a0SJames Wright if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 2453933d9a0SJames Wright 2463933d9a0SJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii)); 2473933d9a0SJames Wright { 2483933d9a0SJames Wright FILE *file; 2493933d9a0SJames Wright 2505037d55dSJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "MatCEED:\n Default COO MatType:%s\n", ctx->coo_mat_type)); 2513933d9a0SJames Wright PetscCall(PetscViewerASCIIGetPointer(viewer, &file)); 2523933d9a0SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " libCEED Operator:\n")); 2533933d9a0SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult, file)); 2543933d9a0SJames Wright if (ctx->op_mult_transpose) { 2553933d9a0SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " libCEED Transpose Operator:\n")); 2563933d9a0SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult_transpose, file)); 2573933d9a0SJames Wright } 2583933d9a0SJames Wright } 2593933d9a0SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2603933d9a0SJames Wright } 2613933d9a0SJames Wright 262c8564c30SJames Wright // ----------------------------------------------------------------------------- 263c8564c30SJames Wright // MatCeed 264c8564c30SJames Wright // ----------------------------------------------------------------------------- 265c8564c30SJames Wright 266c8564c30SJames Wright /** 267c8564c30SJames Wright @brief Create PETSc `Mat` from libCEED operators. 268c8564c30SJames Wright 269c8564c30SJames Wright Collective across MPI processes. 270c8564c30SJames Wright 271c8564c30SJames Wright @param[in] dm_x Input `DM` 272c8564c30SJames Wright @param[in] dm_y Output `DM` 273c8564c30SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 274c8564c30SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 275c8564c30SJames Wright @param[out] mat New MatCeed 276c8564c30SJames Wright 277c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 278c8564c30SJames Wright **/ 279c8564c30SJames Wright PetscErrorCode MatCeedCreate(DM dm_x, DM dm_y, CeedOperator op_mult, CeedOperator op_mult_transpose, Mat *mat) { 280c8564c30SJames Wright PetscInt X_l_size, X_g_size, Y_l_size, Y_g_size; 281c8564c30SJames Wright VecType vec_type; 282c8564c30SJames Wright MatCeedContext ctx; 283c8564c30SJames Wright 284c8564c30SJames Wright PetscFunctionBeginUser; 285c8564c30SJames Wright PetscCall(MatCeedRegisterLogEvents()); 286c8564c30SJames Wright 287c8564c30SJames Wright // Collect context data 288c8564c30SJames Wright PetscCall(DMGetVecType(dm_x, &vec_type)); 289c8564c30SJames Wright { 290c8564c30SJames Wright Vec X; 291c8564c30SJames Wright 292c8564c30SJames Wright PetscCall(DMGetGlobalVector(dm_x, &X)); 293c8564c30SJames Wright PetscCall(VecGetSize(X, &X_g_size)); 294c8564c30SJames Wright PetscCall(VecGetLocalSize(X, &X_l_size)); 295c8564c30SJames Wright PetscCall(DMRestoreGlobalVector(dm_x, &X)); 296c8564c30SJames Wright } 297c8564c30SJames Wright if (dm_y) { 298c8564c30SJames Wright Vec Y; 299c8564c30SJames Wright 300c8564c30SJames Wright PetscCall(DMGetGlobalVector(dm_y, &Y)); 301c8564c30SJames Wright PetscCall(VecGetSize(Y, &Y_g_size)); 302c8564c30SJames Wright PetscCall(VecGetLocalSize(Y, &Y_l_size)); 303c8564c30SJames Wright PetscCall(DMRestoreGlobalVector(dm_y, &Y)); 304c8564c30SJames Wright } else { 305c8564c30SJames Wright dm_y = dm_x; 306c8564c30SJames Wright Y_g_size = X_g_size; 307c8564c30SJames Wright Y_l_size = X_l_size; 308c8564c30SJames Wright } 3095037d55dSJames Wright 310c8564c30SJames Wright // Create context 311c8564c30SJames Wright { 312c8564c30SJames Wright Vec X_loc, Y_loc_transpose = NULL; 313c8564c30SJames Wright 314c8564c30SJames Wright PetscCall(DMCreateLocalVector(dm_x, &X_loc)); 315c8564c30SJames Wright PetscCall(VecZeroEntries(X_loc)); 316c8564c30SJames Wright if (op_mult_transpose) { 317c8564c30SJames Wright PetscCall(DMCreateLocalVector(dm_y, &Y_loc_transpose)); 318c8564c30SJames Wright PetscCall(VecZeroEntries(Y_loc_transpose)); 319c8564c30SJames Wright } 320c8564c30SJames Wright PetscCall(MatCeedContextCreate(dm_x, dm_y, X_loc, Y_loc_transpose, op_mult, op_mult_transpose, MATCEED_MULT, MATCEED_MULT_TRANSPOSE, &ctx)); 321c8564c30SJames Wright PetscCall(VecDestroy(&X_loc)); 322c8564c30SJames Wright PetscCall(VecDestroy(&Y_loc_transpose)); 323c8564c30SJames Wright } 324c8564c30SJames Wright 325c8564c30SJames Wright // Create mat 326c8564c30SJames Wright PetscCall(MatCreateShell(PetscObjectComm((PetscObject)dm_x), Y_l_size, X_l_size, Y_g_size, X_g_size, ctx, mat)); 327c8564c30SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)*mat, MATCEED)); 328c8564c30SJames Wright // -- Set block and variable block sizes 329c8564c30SJames Wright if (dm_x == dm_y) { 330c8564c30SJames Wright MatType dm_mat_type, dm_mat_type_copy; 331c8564c30SJames Wright Mat temp_mat; 332c8564c30SJames Wright 333c8564c30SJames Wright PetscCall(DMGetMatType(dm_x, &dm_mat_type)); 334c8564c30SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 335c8564c30SJames Wright PetscCall(DMSetMatType(dm_x, MATAIJ)); 336c8564c30SJames Wright PetscCall(DMCreateMatrix(dm_x, &temp_mat)); 337c8564c30SJames Wright PetscCall(DMSetMatType(dm_x, dm_mat_type_copy)); 338c8564c30SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 339c8564c30SJames Wright 340c8564c30SJames Wright { 341c8564c30SJames Wright PetscInt block_size, num_blocks, max_vblock_size = PETSC_INT_MAX; 342c8564c30SJames Wright const PetscInt *vblock_sizes; 343c8564c30SJames Wright 344c8564c30SJames Wright // -- Get block sizes 345c8564c30SJames Wright PetscCall(MatGetBlockSize(temp_mat, &block_size)); 346c8564c30SJames Wright PetscCall(MatGetVariableBlockSizes(temp_mat, &num_blocks, &vblock_sizes)); 347c8564c30SJames Wright { 348c8564c30SJames Wright PetscInt local_min_max[2] = {0}, global_min_max[2] = {0, PETSC_INT_MAX}; 349c8564c30SJames Wright 350c8564c30SJames Wright for (PetscInt i = 0; i < num_blocks; i++) local_min_max[1] = PetscMax(local_min_max[1], vblock_sizes[i]); 351c8564c30SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_min_max, global_min_max)); 352c8564c30SJames Wright max_vblock_size = global_min_max[1]; 353c8564c30SJames Wright } 354c8564c30SJames Wright 355c8564c30SJames Wright // -- Copy block sizes 356c8564c30SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(*mat, block_size)); 357c8564c30SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(*mat, num_blocks, (PetscInt *)vblock_sizes)); 358c8564c30SJames Wright 359c8564c30SJames Wright // -- Check libCEED compatibility 360c8564c30SJames Wright { 361c8564c30SJames Wright bool is_composite; 362c8564c30SJames Wright 363c8564c30SJames Wright ctx->is_ceed_pbd_valid = PETSC_TRUE; 364c8564c30SJames Wright ctx->is_ceed_vpbd_valid = PETSC_TRUE; 36554831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorIsComposite(op_mult, &is_composite)); 366c8564c30SJames Wright if (is_composite) { 367c8564c30SJames Wright CeedInt num_sub_operators; 368c8564c30SJames Wright CeedOperator *sub_operators; 369c8564c30SJames Wright 37054831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetNumSub(op_mult, &num_sub_operators)); 37154831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetSubList(op_mult, &sub_operators)); 372c8564c30SJames Wright for (CeedInt i = 0; i < num_sub_operators; i++) { 373c8564c30SJames Wright CeedInt num_bases, num_comp; 374c8564c30SJames Wright CeedBasis *active_bases; 375c8564c30SJames Wright CeedOperatorAssemblyData assembly_data; 376c8564c30SJames Wright 37754831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(sub_operators[i], &assembly_data)); 37854831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 37954831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 380c8564c30SJames Wright if (num_bases > 1) { 381c8564c30SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 382c8564c30SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 383c8564c30SJames Wright } 384c8564c30SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 385c8564c30SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 386c8564c30SJames Wright } 387c8564c30SJames Wright } else { 388c8564c30SJames Wright // LCOV_EXCL_START 389c8564c30SJames Wright CeedInt num_bases, num_comp; 390c8564c30SJames Wright CeedBasis *active_bases; 391c8564c30SJames Wright CeedOperatorAssemblyData assembly_data; 392c8564c30SJames Wright 39354831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(op_mult, &assembly_data)); 39454831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 39554831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 396c8564c30SJames Wright if (num_bases > 1) { 397c8564c30SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 398c8564c30SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 399c8564c30SJames Wright } 400c8564c30SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 401c8564c30SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 402c8564c30SJames Wright // LCOV_EXCL_STOP 403c8564c30SJames Wright } 404c8564c30SJames Wright { 405c8564c30SJames Wright PetscInt local_is_valid[2], global_is_valid[2]; 406c8564c30SJames Wright 407c8564c30SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_pbd_valid; 408c8564c30SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 409c8564c30SJames Wright ctx->is_ceed_pbd_valid = global_is_valid[0]; 410c8564c30SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_vpbd_valid; 411c8564c30SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 412c8564c30SJames Wright ctx->is_ceed_vpbd_valid = global_is_valid[0]; 413c8564c30SJames Wright } 414c8564c30SJames Wright } 415c8564c30SJames Wright } 416c8564c30SJames Wright PetscCall(MatDestroy(&temp_mat)); 417c8564c30SJames Wright } 418c8564c30SJames Wright // -- Set internal mat type 419c8564c30SJames Wright { 420c8564c30SJames Wright VecType vec_type; 4215037d55dSJames Wright MatType coo_mat_type; 422c8564c30SJames Wright 423c8564c30SJames Wright PetscCall(VecGetType(ctx->X_loc, &vec_type)); 4245037d55dSJames Wright if (strstr(vec_type, VECCUDA)) coo_mat_type = MATAIJCUSPARSE; 4255037d55dSJames Wright else if (strstr(vec_type, VECKOKKOS)) coo_mat_type = MATAIJKOKKOS; 4265037d55dSJames Wright else coo_mat_type = MATAIJ; 4275037d55dSJames Wright PetscCall(PetscStrallocpy(coo_mat_type, &ctx->coo_mat_type)); 428c8564c30SJames Wright } 429c8564c30SJames Wright // -- Set mat operations 430c8564c30SJames Wright PetscCall(MatShellSetContextDestroy(*mat, (PetscErrorCode(*)(void *))MatCeedContextDestroy)); 4313933d9a0SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 432c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 433c8564c30SJames Wright if (op_mult_transpose) PetscCall(MatShellSetOperation(*mat, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 434c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 435c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 436c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_INVERT_BLOCK_DIAGONAL, (void (*)(void))MatInvertBlockDiagonal_Ceed)); 437c8564c30SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_INVERT_VBLOCK_DIAGONAL, (void (*)(void))MatInvertVariableBlockDiagonal_Ceed)); 438c8564c30SJames Wright PetscCall(MatShellSetVecType(*mat, vec_type)); 439c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 440c8564c30SJames Wright } 441c8564c30SJames Wright 442c8564c30SJames Wright /** 443c8564c30SJames Wright @brief Copy `MATCEED` into a compatible `Mat` with type `MatShell` or `MATCEED`. 444c8564c30SJames Wright 445c8564c30SJames Wright Collective across MPI processes. 446c8564c30SJames Wright 447c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to copy from 448c8564c30SJames Wright @param[out] mat_other `MatShell` or `MATCEED` to copy into 449c8564c30SJames Wright 450c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 451c8564c30SJames Wright **/ 452c8564c30SJames Wright PetscErrorCode MatCeedCopy(Mat mat_ceed, Mat mat_other) { 453c8564c30SJames Wright PetscFunctionBeginUser; 454c8564c30SJames Wright PetscCall(MatCeedRegisterLogEvents()); 455c8564c30SJames Wright 456c8564c30SJames Wright // Check type compatibility 457c8564c30SJames Wright { 4585037d55dSJames Wright PetscBool is_matceed = PETSC_FALSE, is_matshell = PETSC_FALSE; 459c8564c30SJames Wright MatType mat_type_ceed, mat_type_other; 460c8564c30SJames Wright 461c8564c30SJames Wright PetscCall(MatGetType(mat_ceed, &mat_type_ceed)); 4625037d55dSJames Wright PetscCall(PetscStrcmp(mat_type_ceed, MATCEED, &is_matceed)); 4635037d55dSJames Wright PetscCheck(is_matceed, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_ceed must have type " MATCEED); 4645037d55dSJames Wright PetscCall(MatGetType(mat_other, &mat_type_other)); 4655037d55dSJames Wright PetscCall(PetscStrcmp(mat_type_other, MATCEED, &is_matceed)); 4665037d55dSJames Wright PetscCall(PetscStrcmp(mat_type_other, MATSHELL, &is_matceed)); 4675037d55dSJames Wright PetscCheck(is_matceed || is_matshell, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_other must have type " MATCEED " or " MATSHELL); 468c8564c30SJames Wright } 469c8564c30SJames Wright 470c8564c30SJames Wright // Check dimension compatibility 471c8564c30SJames Wright { 472c8564c30SJames 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; 473c8564c30SJames Wright 474c8564c30SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_ceed_size, &X_g_ceed_size)); 475c8564c30SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_ceed_size, &X_l_ceed_size)); 476c8564c30SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_other_size, &X_g_other_size)); 477c8564c30SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_other_size, &X_l_other_size)); 478c8564c30SJames 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) && 479c8564c30SJames Wright (X_l_ceed_size == X_l_other_size), 480c8564c30SJames Wright PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, 481c8564c30SJames Wright "mat_ceed and mat_other must have compatible sizes; found mat_ceed (Global: %" PetscInt_FMT ", %" PetscInt_FMT 482c8564c30SJames Wright "; Local: %" PetscInt_FMT ", %" PetscInt_FMT ") mat_other (Global: %" PetscInt_FMT ", %" PetscInt_FMT "; Local: %" PetscInt_FMT 483c8564c30SJames Wright ", %" PetscInt_FMT ")", 484c8564c30SJames 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); 485c8564c30SJames Wright } 486c8564c30SJames Wright 487c8564c30SJames Wright // Convert 488c8564c30SJames Wright { 489c8564c30SJames Wright VecType vec_type; 490c8564c30SJames Wright MatCeedContext ctx; 491c8564c30SJames Wright 492c8564c30SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)mat_other, MATCEED)); 493c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 494c8564c30SJames Wright PetscCall(MatCeedContextReference(ctx)); 495c8564c30SJames Wright PetscCall(MatShellSetContext(mat_other, ctx)); 496c8564c30SJames Wright PetscCall(MatShellSetContextDestroy(mat_other, (PetscErrorCode(*)(void *))MatCeedContextDestroy)); 4973933d9a0SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 498c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 499c8564c30SJames Wright if (ctx->op_mult_transpose) PetscCall(MatShellSetOperation(mat_other, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 500c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 501c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 502c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_INVERT_BLOCK_DIAGONAL, (void (*)(void))MatInvertBlockDiagonal_Ceed)); 503c8564c30SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_INVERT_VBLOCK_DIAGONAL, (void (*)(void))MatInvertVariableBlockDiagonal_Ceed)); 504c8564c30SJames Wright { 505c8564c30SJames Wright PetscInt block_size; 506c8564c30SJames Wright 507c8564c30SJames Wright PetscCall(MatGetBlockSize(mat_ceed, &block_size)); 508c8564c30SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(mat_other, block_size)); 509c8564c30SJames Wright } 510c8564c30SJames Wright { 511c8564c30SJames Wright PetscInt num_blocks; 512c8564c30SJames Wright const PetscInt *block_sizes; 513c8564c30SJames Wright 514c8564c30SJames Wright PetscCall(MatGetVariableBlockSizes(mat_ceed, &num_blocks, &block_sizes)); 515c8564c30SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(mat_other, num_blocks, (PetscInt *)block_sizes)); 516c8564c30SJames Wright } 517c8564c30SJames Wright PetscCall(DMGetVecType(ctx->dm_x, &vec_type)); 518c8564c30SJames Wright PetscCall(MatShellSetVecType(mat_other, vec_type)); 519c8564c30SJames Wright } 520c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 521c8564c30SJames Wright } 522c8564c30SJames Wright 523c8564c30SJames Wright /** 5245037d55dSJames Wright @brief Setup a `Mat` with the same COO pattern as a `MatCEED`. 5255037d55dSJames Wright 5265037d55dSJames Wright Collective across MPI processes. 5275037d55dSJames Wright 5285037d55dSJames Wright @param[in] mat_ceed `MATCEED` 5295037d55dSJames Wright @param[out] mat_coo Sparse `Mat` with same COO pattern 5305037d55dSJames Wright 5315037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 5325037d55dSJames Wright **/ 5335037d55dSJames Wright PetscErrorCode MatCeedCreateMatCOO(Mat mat_ceed, Mat *mat_coo) { 5345037d55dSJames Wright MatCeedContext ctx; 5355037d55dSJames Wright 5365037d55dSJames Wright PetscFunctionBeginUser; 5375037d55dSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 5385037d55dSJames Wright 5395037d55dSJames 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"); 5405037d55dSJames Wright 5415037d55dSJames Wright // Check cl mat type 5425037d55dSJames Wright { 5435037d55dSJames Wright PetscBool is_coo_mat_type_cl = PETSC_FALSE; 5445037d55dSJames Wright char coo_mat_type_cl[64]; 5455037d55dSJames Wright 5465037d55dSJames Wright // Check for specific CL coo mat type for this Mat 5475037d55dSJames Wright { 5485037d55dSJames Wright const char *mat_ceed_prefix = NULL; 5495037d55dSJames Wright 5505037d55dSJames Wright PetscCall(MatGetOptionsPrefix(mat_ceed, &mat_ceed_prefix)); 5515037d55dSJames Wright PetscOptionsBegin(PetscObjectComm((PetscObject)mat_ceed), mat_ceed_prefix, "", NULL); 5525037d55dSJames Wright PetscCall(PetscOptionsFList("-ceed_coo_mat_type", "Default MATCEED COO assembly MatType", NULL, MatList, coo_mat_type_cl, coo_mat_type_cl, 5535037d55dSJames Wright sizeof(coo_mat_type_cl), &is_coo_mat_type_cl)); 5545037d55dSJames Wright PetscOptionsEnd(); 5555037d55dSJames Wright if (is_coo_mat_type_cl) { 5565037d55dSJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 5575037d55dSJames Wright PetscCall(PetscStrallocpy(coo_mat_type_cl, &ctx->coo_mat_type)); 5585037d55dSJames Wright } 5595037d55dSJames Wright } 5605037d55dSJames Wright } 5615037d55dSJames Wright 5625037d55dSJames Wright // Create sparse matrix 5635037d55dSJames Wright { 5645037d55dSJames Wright MatType dm_mat_type, dm_mat_type_copy; 5655037d55dSJames Wright 5665037d55dSJames Wright PetscCall(DMGetMatType(ctx->dm_x, &dm_mat_type)); 5675037d55dSJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 5685037d55dSJames Wright PetscCall(DMSetMatType(ctx->dm_x, ctx->coo_mat_type)); 5695037d55dSJames Wright PetscCall(DMCreateMatrix(ctx->dm_x, mat_coo)); 5705037d55dSJames Wright PetscCall(DMSetMatType(ctx->dm_x, dm_mat_type_copy)); 5715037d55dSJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 5725037d55dSJames Wright } 5735037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 5745037d55dSJames Wright } 5755037d55dSJames Wright 5765037d55dSJames Wright /** 5775037d55dSJames Wright @brief Setup the COO preallocation `MATCEED` into a `MATAIJ` or similar. 578c8564c30SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 579c8564c30SJames Wright 580c8564c30SJames Wright Collective across MPI processes. 581c8564c30SJames Wright 582c8564c30SJames Wright @param[in] mat_ceed `MATCEED` to assemble 583c8564c30SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 584c8564c30SJames Wright 585c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 586c8564c30SJames Wright **/ 5875037d55dSJames Wright PetscErrorCode MatCeedSetPreallocationCOO(Mat mat_ceed, Mat mat_coo) { 588c8564c30SJames Wright MatCeedContext ctx; 589c8564c30SJames Wright 590c8564c30SJames Wright PetscFunctionBeginUser; 591c8564c30SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 592c8564c30SJames Wright 593c8564c30SJames Wright { 594c8564c30SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 595c8564c30SJames Wright CeedInt *rows_ceed, *cols_ceed; 596c8564c30SJames Wright PetscCount num_entries; 597c8564c30SJames Wright PetscLogStage stage_amg_setup; 598c8564c30SJames Wright 599c8564c30SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 600c8564c30SJames Wright PetscCall(PetscLogStageGetId("MATCEED Assembly Setup", &stage_amg_setup)); 601c8564c30SJames Wright if (stage_amg_setup == -1) { 602c8564c30SJames Wright PetscCall(PetscLogStageRegister("MATCEED Assembly Setup", &stage_amg_setup)); 603c8564c30SJames Wright } 604c8564c30SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 60554831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 606d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 607d0593705SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 608c8564c30SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 609c8564c30SJames Wright free(rows_petsc); 610c8564c30SJames Wright free(cols_petsc); 61154831c5fSJames Wright if (!ctx->coo_values_full) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_full)); 612c8564c30SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_full * sizeof(Mat), &ctx->mats_assembled_full)); 613c8564c30SJames Wright ctx->mats_assembled_full[ctx->num_mats_assembled_full - 1] = mat_coo; 614c8564c30SJames Wright PetscCall(PetscLogStagePop()); 615c8564c30SJames Wright } 6165037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 6175037d55dSJames Wright } 6185037d55dSJames Wright 6195037d55dSJames Wright /** 6205037d55dSJames Wright @brief Assemble a `MATCEED` into a `MATAIJ` or similar. 6215037d55dSJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 6225037d55dSJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 6235037d55dSJames Wright 6245037d55dSJames Wright Collective across MPI processes. 6255037d55dSJames Wright 6265037d55dSJames Wright @param[in] mat_ceed `MATCEED` to assemble 6275037d55dSJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 6285037d55dSJames Wright 6295037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 6305037d55dSJames Wright **/ 6315037d55dSJames Wright PetscErrorCode MatCeedAssembleCOO(Mat mat_ceed, Mat mat_coo) { 6325037d55dSJames Wright MatCeedContext ctx; 6335037d55dSJames Wright 6345037d55dSJames Wright PetscFunctionBeginUser; 6355037d55dSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 6365037d55dSJames Wright 6375037d55dSJames Wright // Set COO pattern if needed 6385037d55dSJames Wright { 6395037d55dSJames Wright CeedInt index = -1; 6405037d55dSJames Wright 6415037d55dSJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 6425037d55dSJames Wright if (ctx->mats_assembled_full[i] == mat_coo) index = i; 6435037d55dSJames Wright } 6445037d55dSJames Wright if (index == -1) PetscCall(MatCeedSetPreallocationCOO(mat_ceed, mat_coo)); 645c8564c30SJames Wright } 646c8564c30SJames Wright 647c8564c30SJames Wright // Assemble mat_ceed 648c8564c30SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 649c8564c30SJames Wright { 650c8564c30SJames Wright const CeedScalar *values; 651c8564c30SJames Wright MatType mat_type; 652c8564c30SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 653c8564c30SJames Wright PetscBool is_spd, is_spd_known; 654c8564c30SJames Wright 655c8564c30SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 656c8564c30SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 657c8564c30SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 658c8564c30SJames Wright else mem_type = CEED_MEM_HOST; 659c8564c30SJames Wright 66054831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemble(ctx->op_mult, ctx->coo_values_full)); 66154831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_full, mem_type, &values)); 662c8564c30SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 663c8564c30SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 664c8564c30SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 66554831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_full, &values)); 666c8564c30SJames Wright } 667c8564c30SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 668c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 669c8564c30SJames Wright } 670c8564c30SJames Wright 671c8564c30SJames Wright /** 6725037d55dSJames Wright @brief Set the current value of a context field for a `MatCEED`. 6735037d55dSJames Wright 6745037d55dSJames Wright Not collective across MPI processes. 6755037d55dSJames Wright 6765037d55dSJames Wright @param[in,out] mat `MatCEED` 6775037d55dSJames Wright @param[in] name Name of the context field 6785037d55dSJames Wright @param[in] value New context field value 6795037d55dSJames Wright 6805037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 6815037d55dSJames Wright **/ 6825037d55dSJames Wright PetscErrorCode MatCeedSetContextDouble(Mat mat, const char *name, double value) { 6835037d55dSJames Wright PetscBool was_updated = PETSC_FALSE; 6845037d55dSJames Wright MatCeedContext ctx; 6855037d55dSJames Wright 6865037d55dSJames Wright PetscFunctionBeginUser; 6875037d55dSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 6885037d55dSJames Wright { 6895037d55dSJames Wright CeedContextFieldLabel label = NULL; 6905037d55dSJames Wright 6915037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult, name, &label)); 6925037d55dSJames Wright if (label) { 6935037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult, label, &value)); 6945037d55dSJames Wright was_updated = PETSC_TRUE; 6955037d55dSJames Wright } 6965037d55dSJames Wright if (ctx->op_mult_transpose) { 6975037d55dSJames Wright label = NULL; 6985037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult_transpose, name, &label)); 6995037d55dSJames Wright if (label) { 7005037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult_transpose, label, &value)); 7015037d55dSJames Wright was_updated = PETSC_TRUE; 7025037d55dSJames Wright } 7035037d55dSJames Wright } 7045037d55dSJames Wright } 7055037d55dSJames Wright if (was_updated) { 7065037d55dSJames Wright PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 7075037d55dSJames Wright PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 7085037d55dSJames Wright } 7095037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 7105037d55dSJames Wright } 7115037d55dSJames Wright 7125037d55dSJames Wright /** 713*f965f5c6SJames Wright @brief Set the current `PetscReal` value of a context field for a `MatCEED`. 714*f965f5c6SJames Wright 715*f965f5c6SJames Wright Not collective across MPI processes. 716*f965f5c6SJames Wright 717*f965f5c6SJames Wright @param[in,out] mat `MatCEED` 718*f965f5c6SJames Wright @param[in] name Name of the context field 719*f965f5c6SJames Wright @param[in] value New context field value 720*f965f5c6SJames Wright 721*f965f5c6SJames Wright @return An error code: 0 - success, otherwise - failure 722*f965f5c6SJames Wright **/ 723*f965f5c6SJames Wright PetscErrorCode MatCeedSetContextReal(Mat mat, const char *name, PetscReal value) { 724*f965f5c6SJames Wright double value_double = value; 725*f965f5c6SJames Wright 726*f965f5c6SJames Wright PetscFunctionBeginUser; 727*f965f5c6SJames Wright PetscCall(MatCeedSetContextDouble(mat, name, value_double)); 728*f965f5c6SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 729*f965f5c6SJames Wright } 730*f965f5c6SJames Wright 731*f965f5c6SJames Wright /** 7325037d55dSJames Wright @brief Get the current value of a context field for a `MatCEED`. 7335037d55dSJames Wright 7345037d55dSJames Wright Not collective across MPI processes. 7355037d55dSJames Wright 7365037d55dSJames Wright @param[in] mat `MatCEED` 7375037d55dSJames Wright @param[in] name Name of the context field 7385037d55dSJames Wright @param[out] value Current context field value 7395037d55dSJames Wright 7405037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 7415037d55dSJames Wright **/ 7425037d55dSJames Wright PetscErrorCode MatCeedGetContextDouble(Mat mat, const char *name, double *value) { 7435037d55dSJames Wright MatCeedContext ctx; 7445037d55dSJames Wright 7455037d55dSJames Wright PetscFunctionBeginUser; 7465037d55dSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 7475037d55dSJames Wright { 7485037d55dSJames Wright CeedContextFieldLabel label = NULL; 7495037d55dSJames Wright CeedOperator op = ctx->op_mult; 7505037d55dSJames Wright 7515037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 7525037d55dSJames Wright if (!label && ctx->op_mult_transpose) { 7535037d55dSJames Wright op = ctx->op_mult_transpose; 7545037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 7555037d55dSJames Wright } 7565037d55dSJames Wright if (label) { 7575037d55dSJames Wright PetscSizeT num_values; 7585037d55dSJames Wright const double *values_ceed; 7595037d55dSJames Wright 7605037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextDoubleRead(op, label, &num_values, &values_ceed)); 7615037d55dSJames Wright *value = values_ceed[0]; 7625037d55dSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorRestoreContextDoubleRead(op, label, &values_ceed)); 7635037d55dSJames Wright } 7645037d55dSJames Wright } 7655037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 7665037d55dSJames Wright } 7675037d55dSJames Wright 7685037d55dSJames Wright /** 769*f965f5c6SJames Wright @brief Get the current `PetscReal` value of a context field for a `MatCEED`. 770*f965f5c6SJames Wright 771*f965f5c6SJames Wright Not collective across MPI processes. 772*f965f5c6SJames Wright 773*f965f5c6SJames Wright @param[in] mat `MatCEED` 774*f965f5c6SJames Wright @param[in] name Name of the context field 775*f965f5c6SJames Wright @param[out] value Current context field value 776*f965f5c6SJames Wright 777*f965f5c6SJames Wright @return An error code: 0 - success, otherwise - failure 778*f965f5c6SJames Wright **/ 779*f965f5c6SJames Wright PetscErrorCode MatCeedGetContextReal(Mat mat, const char *name, PetscReal *value) { 780*f965f5c6SJames Wright double value_double; 781*f965f5c6SJames Wright 782*f965f5c6SJames Wright PetscFunctionBeginUser; 783*f965f5c6SJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &value_double)); 784*f965f5c6SJames Wright *value = value_double; 785*f965f5c6SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 786*f965f5c6SJames Wright } 787*f965f5c6SJames Wright 788*f965f5c6SJames Wright /** 789c8564c30SJames Wright @brief Set user context for a `MATCEED`. 790c8564c30SJames Wright 791c8564c30SJames Wright Collective across MPI processes. 792c8564c30SJames Wright 793c8564c30SJames Wright @param[in,out] mat `MATCEED` 794c8564c30SJames Wright @param[in] f The context destroy function, or NULL 795c8564c30SJames Wright @param[in] ctx User context, or NULL to unset 796c8564c30SJames Wright 797c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 798c8564c30SJames Wright **/ 799c8564c30SJames Wright PetscErrorCode MatCeedSetContext(Mat mat, PetscErrorCode (*f)(void *), void *ctx) { 800c8564c30SJames Wright PetscContainer user_ctx = NULL; 801c8564c30SJames Wright 802c8564c30SJames Wright PetscFunctionBeginUser; 803c8564c30SJames Wright if (ctx) { 804c8564c30SJames Wright PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)mat), &user_ctx)); 805c8564c30SJames Wright PetscCall(PetscContainerSetPointer(user_ctx, ctx)); 806c8564c30SJames Wright PetscCall(PetscContainerSetUserDestroy(user_ctx, f)); 807c8564c30SJames Wright } 808c8564c30SJames Wright PetscCall(PetscObjectCompose((PetscObject)mat, "MatCeed user context", (PetscObject)user_ctx)); 809c8564c30SJames Wright PetscCall(PetscContainerDestroy(&user_ctx)); 810c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 811c8564c30SJames Wright } 812c8564c30SJames Wright 813c8564c30SJames Wright /** 814c8564c30SJames Wright @brief Retrieve the user context for a `MATCEED`. 815c8564c30SJames Wright 816c8564c30SJames Wright Collective across MPI processes. 817c8564c30SJames Wright 818c8564c30SJames Wright @param[in,out] mat `MATCEED` 819c8564c30SJames Wright @param[in] ctx User context 820c8564c30SJames Wright 821c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 822c8564c30SJames Wright **/ 823c8564c30SJames Wright PetscErrorCode MatCeedGetContext(Mat mat, void *ctx) { 824c8564c30SJames Wright PetscContainer user_ctx; 825c8564c30SJames Wright 826c8564c30SJames Wright PetscFunctionBeginUser; 827c8564c30SJames Wright PetscCall(PetscObjectQuery((PetscObject)mat, "MatCeed user context", (PetscObject *)&user_ctx)); 828c8564c30SJames Wright if (user_ctx) PetscCall(PetscContainerGetPointer(user_ctx, (void **)ctx)); 829c8564c30SJames Wright else *(void **)ctx = NULL; 830c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 831c8564c30SJames Wright } 832c8564c30SJames Wright /** 8335037d55dSJames Wright @brief Set a user defined matrix operation for a `MATCEED` matrix. 8345037d55dSJames Wright 8355037d55dSJames Wright Within each user-defined routine, the user should call `MatCeedGetContext()` to obtain the user-defined context that was set by 8365037d55dSJames Wright `MatCeedSetContext()`. 837c8564c30SJames Wright 838c8564c30SJames Wright Collective across MPI processes. 839c8564c30SJames Wright 840c8564c30SJames Wright @param[in,out] mat `MATCEED` 8415037d55dSJames Wright @param[in] op Name of the `MatOperation` 8425037d55dSJames Wright @param[in] g Function that provides the operation 843c8564c30SJames Wright 844c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 845c8564c30SJames Wright **/ 8465037d55dSJames Wright PetscErrorCode MatCeedSetOperation(Mat mat, MatOperation op, void (*g)(void)) { 8475037d55dSJames Wright PetscFunctionBeginUser; 8485037d55dSJames Wright PetscCall(MatShellSetOperation(mat, op, g)); 8495037d55dSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 8505037d55dSJames Wright } 8515037d55dSJames Wright 8525037d55dSJames Wright /** 8535037d55dSJames Wright @brief Sets the default COO matrix type as a string from the `MATCEED`. 8545037d55dSJames Wright 8555037d55dSJames Wright Collective across MPI processes. 8565037d55dSJames Wright 8575037d55dSJames Wright @param[in,out] mat `MATCEED` 8585037d55dSJames Wright @param[in] type COO `MatType` to set 8595037d55dSJames Wright 8605037d55dSJames Wright @return An error code: 0 - success, otherwise - failure 8615037d55dSJames Wright **/ 8625037d55dSJames Wright PetscErrorCode MatCeedSetCOOMatType(Mat mat, MatType type) { 863c8564c30SJames Wright MatCeedContext ctx; 864c8564c30SJames Wright 865c8564c30SJames Wright PetscFunctionBeginUser; 866c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 867c8564c30SJames Wright // Check if same 868c8564c30SJames Wright { 869c8564c30SJames Wright size_t len_old, len_new; 870c8564c30SJames Wright PetscBool is_same = PETSC_FALSE; 871c8564c30SJames Wright 8725037d55dSJames Wright PetscCall(PetscStrlen(ctx->coo_mat_type, &len_old)); 873c8564c30SJames Wright PetscCall(PetscStrlen(type, &len_new)); 8745037d55dSJames Wright if (len_old == len_new) PetscCall(PetscStrncmp(ctx->coo_mat_type, type, len_old, &is_same)); 875c8564c30SJames Wright if (is_same) PetscFunctionReturn(PETSC_SUCCESS); 876c8564c30SJames Wright } 877c8564c30SJames Wright // Clean up old mats in different format 878c8564c30SJames Wright // LCOV_EXCL_START 879c8564c30SJames Wright if (ctx->mat_assembled_full_internal) { 880c8564c30SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 881c8564c30SJames Wright if (ctx->mats_assembled_full[i] == ctx->mat_assembled_full_internal) { 882c8564c30SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_full; j++) { 883c8564c30SJames Wright ctx->mats_assembled_full[j - 1] = ctx->mats_assembled_full[j]; 884c8564c30SJames Wright } 885c8564c30SJames Wright ctx->num_mats_assembled_full--; 886c8564c30SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 887c8564c30SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 888c8564c30SJames Wright } 889c8564c30SJames Wright } 890c8564c30SJames Wright } 891c8564c30SJames Wright if (ctx->mat_assembled_pbd_internal) { 892c8564c30SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 893c8564c30SJames Wright if (ctx->mats_assembled_pbd[i] == ctx->mat_assembled_pbd_internal) { 894c8564c30SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_pbd; j++) { 895c8564c30SJames Wright ctx->mats_assembled_pbd[j - 1] = ctx->mats_assembled_pbd[j]; 896c8564c30SJames Wright } 897c8564c30SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 898c8564c30SJames Wright ctx->num_mats_assembled_pbd--; 899c8564c30SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 900c8564c30SJames Wright } 901c8564c30SJames Wright } 902c8564c30SJames Wright } 9035037d55dSJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 9045037d55dSJames Wright PetscCall(PetscStrallocpy(type, &ctx->coo_mat_type)); 905c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 906c8564c30SJames Wright // LCOV_EXCL_STOP 907c8564c30SJames Wright } 908c8564c30SJames Wright 909c8564c30SJames Wright /** 9105037d55dSJames Wright @brief Gets the default COO matrix type as a string from the `MATCEED`. 911c8564c30SJames Wright 912c8564c30SJames Wright Collective across MPI processes. 913c8564c30SJames Wright 914c8564c30SJames Wright @param[in,out] mat `MATCEED` 9155037d55dSJames Wright @param[in] type COO `MatType` 916c8564c30SJames Wright 917c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 918c8564c30SJames Wright **/ 9195037d55dSJames Wright PetscErrorCode MatCeedGetCOOMatType(Mat mat, MatType *type) { 920c8564c30SJames Wright MatCeedContext ctx; 921c8564c30SJames Wright 922c8564c30SJames Wright PetscFunctionBeginUser; 923c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 9245037d55dSJames Wright *type = ctx->coo_mat_type; 925c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 926c8564c30SJames Wright } 927c8564c30SJames Wright 928c8564c30SJames Wright /** 929c8564c30SJames Wright @brief Set input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 930c8564c30SJames Wright 931c8564c30SJames Wright Not collective across MPI processes. 932c8564c30SJames Wright 933c8564c30SJames Wright @param[in,out] mat `MATCEED` 934c8564c30SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 935c8564c30SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 936c8564c30SJames Wright 937c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 938c8564c30SJames Wright **/ 939c8564c30SJames Wright PetscErrorCode MatCeedSetLocalVectors(Mat mat, Vec X_loc, Vec Y_loc_transpose) { 940c8564c30SJames Wright MatCeedContext ctx; 941c8564c30SJames Wright 942c8564c30SJames Wright PetscFunctionBeginUser; 943c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 944c8564c30SJames Wright if (X_loc) { 945c8564c30SJames Wright PetscInt len_old, len_new; 946c8564c30SJames Wright 947c8564c30SJames Wright PetscCall(VecGetSize(ctx->X_loc, &len_old)); 948c8564c30SJames Wright PetscCall(VecGetSize(X_loc, &len_new)); 949c8564c30SJames 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, 950c8564c30SJames Wright len_new, len_old); 9515037d55dSJames Wright PetscCall(VecReferenceCopy(X_loc, &ctx->X_loc)); 952c8564c30SJames Wright } 953c8564c30SJames Wright if (Y_loc_transpose) { 954c8564c30SJames Wright PetscInt len_old, len_new; 955c8564c30SJames Wright 956c8564c30SJames Wright PetscCall(VecGetSize(ctx->Y_loc_transpose, &len_old)); 957c8564c30SJames Wright PetscCall(VecGetSize(Y_loc_transpose, &len_new)); 958c8564c30SJames Wright PetscCheck(len_old == len_new, PETSC_COMM_SELF, PETSC_ERR_LIB, 959c8564c30SJames Wright "new Y_loc_transpose length %" PetscInt_FMT " should match old Y_loc_transpose length %" PetscInt_FMT, len_new, len_old); 9605037d55dSJames Wright PetscCall(VecReferenceCopy(Y_loc_transpose, &ctx->Y_loc_transpose)); 961c8564c30SJames Wright } 962c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 963c8564c30SJames Wright } 964c8564c30SJames Wright 965c8564c30SJames Wright /** 966c8564c30SJames Wright @brief Get input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 967c8564c30SJames Wright 968c8564c30SJames Wright Not collective across MPI processes. 969c8564c30SJames Wright 970c8564c30SJames Wright @param[in,out] mat `MATCEED` 971c8564c30SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 972c8564c30SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 973c8564c30SJames Wright 974c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 975c8564c30SJames Wright **/ 976c8564c30SJames Wright PetscErrorCode MatCeedGetLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 977c8564c30SJames Wright MatCeedContext ctx; 978c8564c30SJames Wright 979c8564c30SJames Wright PetscFunctionBeginUser; 980c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 981c8564c30SJames Wright if (X_loc) { 9825037d55dSJames Wright *X_loc = NULL; 9835037d55dSJames Wright PetscCall(VecReferenceCopy(ctx->X_loc, X_loc)); 984c8564c30SJames Wright } 985c8564c30SJames Wright if (Y_loc_transpose) { 9865037d55dSJames Wright *Y_loc_transpose = NULL; 9875037d55dSJames Wright PetscCall(VecReferenceCopy(ctx->Y_loc_transpose, Y_loc_transpose)); 988c8564c30SJames Wright } 989c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 990c8564c30SJames Wright } 991c8564c30SJames Wright 992c8564c30SJames Wright /** 993c8564c30SJames Wright @brief Restore input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 994c8564c30SJames Wright 995c8564c30SJames Wright Not collective across MPI processes. 996c8564c30SJames Wright 997c8564c30SJames Wright @param[in,out] mat MatCeed 998c8564c30SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 999c8564c30SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 1000c8564c30SJames Wright 1001c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1002c8564c30SJames Wright **/ 1003c8564c30SJames Wright PetscErrorCode MatCeedRestoreLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 1004c8564c30SJames Wright PetscFunctionBeginUser; 1005c8564c30SJames Wright if (X_loc) PetscCall(VecDestroy(X_loc)); 1006c8564c30SJames Wright if (Y_loc_transpose) PetscCall(VecDestroy(Y_loc_transpose)); 1007c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1008c8564c30SJames Wright } 1009c8564c30SJames Wright 1010c8564c30SJames Wright /** 1011c8564c30SJames Wright @brief Get libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 1012c8564c30SJames Wright 1013c8564c30SJames Wright Not collective across MPI processes. 1014c8564c30SJames Wright 1015c8564c30SJames Wright @param[in,out] mat MatCeed 1016c8564c30SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 1017c8564c30SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 1018c8564c30SJames Wright 1019c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1020c8564c30SJames Wright **/ 1021c8564c30SJames Wright PetscErrorCode MatCeedGetCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 1022c8564c30SJames Wright MatCeedContext ctx; 1023c8564c30SJames Wright 1024c8564c30SJames Wright PetscFunctionBeginUser; 1025c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1026c8564c30SJames Wright if (op_mult) { 1027c8564c30SJames Wright *op_mult = NULL; 102854831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult, op_mult)); 1029c8564c30SJames Wright } 1030c8564c30SJames Wright if (op_mult_transpose) { 1031c8564c30SJames Wright *op_mult_transpose = NULL; 103254831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult_transpose, op_mult_transpose)); 1033c8564c30SJames Wright } 1034c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1035c8564c30SJames Wright } 1036c8564c30SJames Wright 1037c8564c30SJames Wright /** 1038c8564c30SJames Wright @brief Restore libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 1039c8564c30SJames Wright 1040c8564c30SJames Wright Not collective across MPI processes. 1041c8564c30SJames Wright 1042c8564c30SJames Wright @param[in,out] mat MatCeed 1043c8564c30SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 1044c8564c30SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 1045c8564c30SJames Wright 1046c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1047c8564c30SJames Wright **/ 1048c8564c30SJames Wright PetscErrorCode MatCeedRestoreCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 1049c8564c30SJames Wright MatCeedContext ctx; 1050c8564c30SJames Wright 1051c8564c30SJames Wright PetscFunctionBeginUser; 1052c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 105354831c5fSJames Wright if (op_mult) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult)); 105454831c5fSJames Wright if (op_mult_transpose) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult_transpose)); 1055c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1056c8564c30SJames Wright } 1057c8564c30SJames Wright 1058c8564c30SJames Wright /** 1059c8564c30SJames Wright @brief Set `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1060c8564c30SJames Wright 1061c8564c30SJames Wright Not collective across MPI processes. 1062c8564c30SJames Wright 1063c8564c30SJames Wright @param[in,out] mat MatCeed 1064c8564c30SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 1065c8564c30SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 1066c8564c30SJames Wright 1067c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1068c8564c30SJames Wright **/ 1069c8564c30SJames Wright PetscErrorCode MatCeedSetLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 1070c8564c30SJames Wright MatCeedContext ctx; 1071c8564c30SJames Wright 1072c8564c30SJames Wright PetscFunctionBeginUser; 1073c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1074c8564c30SJames Wright if (log_event_mult) ctx->log_event_mult = log_event_mult; 1075c8564c30SJames Wright if (log_event_mult_transpose) ctx->log_event_mult_transpose = log_event_mult_transpose; 1076c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1077c8564c30SJames Wright } 1078c8564c30SJames Wright 1079c8564c30SJames Wright /** 1080c8564c30SJames Wright @brief Get `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1081c8564c30SJames Wright 1082c8564c30SJames Wright Not collective across MPI processes. 1083c8564c30SJames Wright 1084c8564c30SJames Wright @param[in,out] mat MatCeed 1085c8564c30SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 1086c8564c30SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 1087c8564c30SJames Wright 1088c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1089c8564c30SJames Wright **/ 1090c8564c30SJames Wright PetscErrorCode MatCeedGetLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 1091c8564c30SJames Wright MatCeedContext ctx; 1092c8564c30SJames Wright 1093c8564c30SJames Wright PetscFunctionBeginUser; 1094c8564c30SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1095c8564c30SJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_mult; 1096c8564c30SJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_mult_transpose; 1097c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1098c8564c30SJames Wright } 1099c8564c30SJames Wright 1100c8564c30SJames Wright // ----------------------------------------------------------------------------- 1101c8564c30SJames Wright // Operator context data 1102c8564c30SJames Wright // ----------------------------------------------------------------------------- 1103c8564c30SJames Wright 1104c8564c30SJames Wright /** 1105c8564c30SJames Wright @brief Setup context data for operator application. 1106c8564c30SJames Wright 1107c8564c30SJames Wright Collective across MPI processes. 1108c8564c30SJames Wright 1109c8564c30SJames Wright @param[in] dm_x Input `DM` 1110c8564c30SJames Wright @param[in] dm_y Output `DM` 1111c8564c30SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 1112c8564c30SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 1113c8564c30SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 1114c8564c30SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 1115c8564c30SJames Wright @param[in] log_event_mult `PetscLogEvent` for forward evaluation 1116c8564c30SJames Wright @param[in] log_event_mult_transpose `PetscLogEvent` for transpose evaluation 1117c8564c30SJames Wright @param[out] ctx Context data for operator evaluation 1118c8564c30SJames Wright 1119c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1120c8564c30SJames Wright **/ 1121c8564c30SJames Wright PetscErrorCode MatCeedContextCreate(DM dm_x, DM dm_y, Vec X_loc, Vec Y_loc_transpose, CeedOperator op_mult, CeedOperator op_mult_transpose, 1122c8564c30SJames Wright PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose, MatCeedContext *ctx) { 1123c8564c30SJames Wright CeedSize x_loc_len, y_loc_len; 1124c8564c30SJames Wright 1125c8564c30SJames Wright PetscFunctionBeginUser; 1126c8564c30SJames Wright 1127c8564c30SJames Wright // Allocate 1128c8564c30SJames Wright PetscCall(PetscNew(ctx)); 1129c8564c30SJames Wright (*ctx)->ref_count = 1; 1130c8564c30SJames Wright 1131c8564c30SJames Wright // Logging 1132c8564c30SJames Wright (*ctx)->log_event_mult = log_event_mult; 1133c8564c30SJames Wright (*ctx)->log_event_mult_transpose = log_event_mult_transpose; 1134c8564c30SJames Wright 1135c8564c30SJames Wright // PETSc objects 11365037d55dSJames Wright PetscCall(DMReferenceCopy(dm_x, &(*ctx)->dm_x)); 11375037d55dSJames Wright PetscCall(DMReferenceCopy(dm_y, &(*ctx)->dm_y)); 11385037d55dSJames Wright if (X_loc) PetscCall(VecReferenceCopy(X_loc, &(*ctx)->X_loc)); 11395037d55dSJames Wright if (Y_loc_transpose) PetscCall(VecReferenceCopy(Y_loc_transpose, &(*ctx)->Y_loc_transpose)); 1140c8564c30SJames Wright 1141c8564c30SJames Wright // Memtype 1142c8564c30SJames Wright { 1143c8564c30SJames Wright const PetscScalar *x; 1144c8564c30SJames Wright Vec X; 1145c8564c30SJames Wright 1146c8564c30SJames Wright PetscCall(DMGetLocalVector(dm_x, &X)); 1147c8564c30SJames Wright PetscCall(VecGetArrayReadAndMemType(X, &x, &(*ctx)->mem_type)); 1148c8564c30SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X, &x)); 1149c8564c30SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &X)); 1150c8564c30SJames Wright } 1151c8564c30SJames Wright 1152c8564c30SJames Wright // libCEED objects 1153c8564c30SJames Wright PetscCheck(CeedOperatorGetCeed(op_mult, &(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, 1154c8564c30SJames Wright "retrieving Ceed context object failed"); 115554831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedReference((*ctx)->ceed)); 115654831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetActiveVectorLengths(op_mult, &x_loc_len, &y_loc_len)); 115754831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult, &(*ctx)->op_mult)); 115854831c5fSJames Wright if (op_mult_transpose) PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult_transpose, &(*ctx)->op_mult_transpose)); 115954831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, x_loc_len, &(*ctx)->x_loc)); 116054831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, y_loc_len, &(*ctx)->y_loc)); 1161c8564c30SJames Wright 1162c8564c30SJames Wright // Flop counting 1163c8564c30SJames Wright { 1164c8564c30SJames Wright CeedSize ceed_flops_estimate = 0; 1165c8564c30SJames Wright 116654831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult, &ceed_flops_estimate)); 1167c8564c30SJames Wright (*ctx)->flops_mult = ceed_flops_estimate; 1168c8564c30SJames Wright if (op_mult_transpose) { 116954831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult_transpose, &ceed_flops_estimate)); 1170c8564c30SJames Wright (*ctx)->flops_mult_transpose = ceed_flops_estimate; 1171c8564c30SJames Wright } 1172c8564c30SJames Wright } 1173c8564c30SJames Wright 1174c8564c30SJames Wright // Check sizes 1175c8564c30SJames Wright if (x_loc_len > 0 || y_loc_len > 0) { 1176c8564c30SJames Wright CeedSize ctx_x_loc_len, ctx_y_loc_len; 1177c8564c30SJames Wright PetscInt X_loc_len, dm_x_loc_len, Y_loc_len, dm_y_loc_len; 1178c8564c30SJames Wright Vec dm_X_loc, dm_Y_loc; 1179c8564c30SJames Wright 1180c8564c30SJames Wright // -- Input 1181c8564c30SJames Wright PetscCall(DMGetLocalVector(dm_x, &dm_X_loc)); 1182c8564c30SJames Wright PetscCall(VecGetLocalSize(dm_X_loc, &dm_x_loc_len)); 1183c8564c30SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &dm_X_loc)); 118454831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->x_loc, &ctx_x_loc_len)); 1185c86b9822SJames Wright if (X_loc) { 1186c86b9822SJames Wright PetscCall(VecGetLocalSize(X_loc, &X_loc_len)); 1187c86b9822SJames Wright PetscCheck(X_loc_len == dm_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 1188c86b9822SJames Wright "X_loc (%" PetscInt_FMT ") must match dm_x (%" PetscInt_FMT ") dimensions", X_loc_len, dm_x_loc_len); 1189c86b9822SJames Wright } 1190c86b9822SJames 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", 1191c86b9822SJames Wright x_loc_len, dm_x_loc_len); 1192c86b9822SJames 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 ")", 1193c86b9822SJames Wright x_loc_len, ctx_x_loc_len); 1194c8564c30SJames Wright 1195c8564c30SJames Wright // -- Output 1196c8564c30SJames Wright PetscCall(DMGetLocalVector(dm_y, &dm_Y_loc)); 1197c8564c30SJames Wright PetscCall(VecGetLocalSize(dm_Y_loc, &dm_y_loc_len)); 1198c8564c30SJames Wright PetscCall(DMRestoreLocalVector(dm_y, &dm_Y_loc)); 119954831c5fSJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->y_loc, &ctx_y_loc_len)); 1200c86b9822SJames 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", 1201c86b9822SJames Wright ctx_y_loc_len, dm_y_loc_len); 1202c8564c30SJames Wright 1203c8564c30SJames Wright // -- Transpose 1204c8564c30SJames Wright if (Y_loc_transpose) { 1205c8564c30SJames Wright PetscCall(VecGetLocalSize(Y_loc_transpose, &Y_loc_len)); 1206c86b9822SJames Wright PetscCheck(Y_loc_len == dm_y_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 1207c86b9822SJames Wright "Y_loc_transpose (%" PetscInt_FMT ") must match dm_y (%" PetscInt_FMT ") dimensions", Y_loc_len, dm_y_loc_len); 1208c8564c30SJames Wright } 1209c8564c30SJames Wright } 1210c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1211c8564c30SJames Wright } 1212c8564c30SJames Wright 1213c8564c30SJames Wright /** 1214c8564c30SJames Wright @brief Increment reference counter for `MATCEED` context. 1215c8564c30SJames Wright 1216c8564c30SJames Wright Not collective across MPI processes. 1217c8564c30SJames Wright 1218c8564c30SJames Wright @param[in,out] ctx Context data 1219c8564c30SJames Wright 1220c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1221c8564c30SJames Wright **/ 1222c8564c30SJames Wright PetscErrorCode MatCeedContextReference(MatCeedContext ctx) { 1223c8564c30SJames Wright PetscFunctionBeginUser; 1224c8564c30SJames Wright ctx->ref_count++; 1225c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1226c8564c30SJames Wright } 1227c8564c30SJames Wright 1228c8564c30SJames Wright /** 1229c8564c30SJames Wright @brief Copy reference for `MATCEED`. 1230c8564c30SJames Wright Note: If `ctx_copy` is non-null, it is assumed to be a valid pointer to a `MatCeedContext`. 1231c8564c30SJames Wright 1232c8564c30SJames Wright Not collective across MPI processes. 1233c8564c30SJames Wright 1234c8564c30SJames Wright @param[in] ctx Context data 1235c8564c30SJames Wright @param[out] ctx_copy Copy of pointer to context data 1236c8564c30SJames Wright 1237c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1238c8564c30SJames Wright **/ 1239c8564c30SJames Wright PetscErrorCode MatCeedContextReferenceCopy(MatCeedContext ctx, MatCeedContext *ctx_copy) { 1240c8564c30SJames Wright PetscFunctionBeginUser; 1241c8564c30SJames Wright PetscCall(MatCeedContextReference(ctx)); 1242c8564c30SJames Wright PetscCall(MatCeedContextDestroy(*ctx_copy)); 1243c8564c30SJames Wright *ctx_copy = ctx; 1244c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1245c8564c30SJames Wright } 1246c8564c30SJames Wright 1247c8564c30SJames Wright /** 1248c8564c30SJames Wright @brief Destroy context data for operator application. 1249c8564c30SJames Wright 1250c8564c30SJames Wright Collective across MPI processes. 1251c8564c30SJames Wright 1252c8564c30SJames Wright @param[in,out] ctx Context data for operator evaluation 1253c8564c30SJames Wright 1254c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1255c8564c30SJames Wright **/ 1256c8564c30SJames Wright PetscErrorCode MatCeedContextDestroy(MatCeedContext ctx) { 1257c8564c30SJames Wright PetscFunctionBeginUser; 1258c8564c30SJames Wright if (!ctx || --ctx->ref_count > 0) PetscFunctionReturn(PETSC_SUCCESS); 1259c8564c30SJames Wright 1260c8564c30SJames Wright // PETSc objects 1261c8564c30SJames Wright PetscCall(DMDestroy(&ctx->dm_x)); 1262c8564c30SJames Wright PetscCall(DMDestroy(&ctx->dm_y)); 1263c8564c30SJames Wright PetscCall(VecDestroy(&ctx->X_loc)); 1264c8564c30SJames Wright PetscCall(VecDestroy(&ctx->Y_loc_transpose)); 1265c8564c30SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 1266c8564c30SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 12675037d55dSJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 1268c8564c30SJames Wright PetscCall(PetscFree(ctx->mats_assembled_full)); 1269c8564c30SJames Wright PetscCall(PetscFree(ctx->mats_assembled_pbd)); 1270c8564c30SJames Wright 1271c8564c30SJames Wright // libCEED objects 127254831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->x_loc)); 127354831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->y_loc)); 127454831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->coo_values_full)); 127554831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->coo_values_pbd)); 127654831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorDestroy(&ctx->op_mult)); 127754831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorDestroy(&ctx->op_mult_transpose)); 1278c8564c30SJames Wright PetscCheck(CeedDestroy(&ctx->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, "destroying libCEED context object failed"); 1279c8564c30SJames Wright 1280c8564c30SJames Wright // Deallocate 1281c8564c30SJames Wright ctx->is_destroyed = PETSC_TRUE; // Flag as destroyed in case someone has stale ref 1282c8564c30SJames Wright PetscCall(PetscFree(ctx)); 1283c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1284c8564c30SJames Wright } 1285c8564c30SJames Wright 1286c8564c30SJames Wright /** 1287c8564c30SJames Wright @brief Compute the diagonal of an operator via libCEED. 1288c8564c30SJames Wright 1289c8564c30SJames Wright Collective across MPI processes. 1290c8564c30SJames Wright 1291c8564c30SJames Wright @param[in] A `MATCEED` 1292c8564c30SJames Wright @param[out] D Vector holding operator diagonal 1293c8564c30SJames Wright 1294c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1295c8564c30SJames Wright **/ 1296c8564c30SJames Wright PetscErrorCode MatGetDiagonal_Ceed(Mat A, Vec D) { 1297c8564c30SJames Wright PetscMemType mem_type; 1298c8564c30SJames Wright Vec D_loc; 1299c8564c30SJames Wright MatCeedContext ctx; 1300c8564c30SJames Wright 1301c8564c30SJames Wright PetscFunctionBeginUser; 1302c8564c30SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1303c8564c30SJames Wright 1304c8564c30SJames Wright // Place PETSc vector in libCEED vector 1305c8564c30SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &D_loc)); 1306d0593705SJames Wright PetscCall(VecPetscToCeed(D_loc, &mem_type, ctx->x_loc)); 1307c8564c30SJames Wright 1308c8564c30SJames Wright // Compute Diagonal 130954831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleDiagonal(ctx->op_mult, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1310c8564c30SJames Wright 1311c8564c30SJames Wright // Restore PETSc vector 1312d0593705SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, mem_type, D_loc)); 1313c8564c30SJames Wright 1314c8564c30SJames Wright // Local-to-Global 1315c8564c30SJames Wright PetscCall(VecZeroEntries(D)); 1316c8564c30SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, D_loc, ADD_VALUES, D)); 1317c8564c30SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &D_loc)); 1318c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1319c8564c30SJames Wright } 1320c8564c30SJames Wright 1321c8564c30SJames Wright /** 1322c8564c30SJames Wright @brief Compute `A X = Y` for a `MATCEED`. 1323c8564c30SJames Wright 1324c8564c30SJames Wright Collective across MPI processes. 1325c8564c30SJames Wright 1326c8564c30SJames Wright @param[in] A `MATCEED` 1327c8564c30SJames Wright @param[in] X Input PETSc vector 1328c8564c30SJames Wright @param[out] Y Output PETSc vector 1329c8564c30SJames Wright 1330c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1331c8564c30SJames Wright **/ 1332c8564c30SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 1333c8564c30SJames Wright MatCeedContext ctx; 1334c8564c30SJames Wright 1335c8564c30SJames Wright PetscFunctionBeginUser; 1336c8564c30SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1337c8564c30SJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult, A, X, Y, 0)); 1338c8564c30SJames Wright 1339c8564c30SJames Wright { 1340c8564c30SJames Wright PetscMemType x_mem_type, y_mem_type; 1341c8564c30SJames Wright Vec X_loc = ctx->X_loc, Y_loc; 1342c8564c30SJames Wright 1343c8564c30SJames Wright // Get local vectors 1344c8564c30SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 1345c8564c30SJames Wright PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 1346c8564c30SJames Wright 1347c8564c30SJames Wright // Global-to-local 1348c8564c30SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc)); 1349c8564c30SJames Wright 1350c8564c30SJames Wright // Setup libCEED vectors 1351d0593705SJames Wright PetscCall(VecReadPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 1352c8564c30SJames Wright PetscCall(VecZeroEntries(Y_loc)); 1353d0593705SJames Wright PetscCall(VecPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 1354c8564c30SJames Wright 1355c8564c30SJames Wright // Apply libCEED operator 1356c8564c30SJames Wright PetscCall(PetscLogGpuTimeBegin()); 135754831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult, ctx->x_loc, ctx->y_loc, CEED_REQUEST_IMMEDIATE)); 1358c8564c30SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1359c8564c30SJames Wright 1360c8564c30SJames Wright // Restore PETSc vectors 1361d0593705SJames Wright PetscCall(VecReadCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1362d0593705SJames Wright PetscCall(VecCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1363c8564c30SJames Wright 1364c8564c30SJames Wright // Local-to-global 1365c8564c30SJames Wright PetscCall(VecZeroEntries(Y)); 1366c8564c30SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y)); 1367c8564c30SJames Wright 1368c8564c30SJames Wright // Restore local vectors, as needed 1369c8564c30SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 1370c8564c30SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 1371c8564c30SJames Wright } 1372c8564c30SJames Wright 1373c8564c30SJames Wright // Log flops 1374c8564c30SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult)); 1375c8564c30SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult)); 1376c8564c30SJames Wright 1377c8564c30SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult, A, X, Y, 0)); 1378c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1379c8564c30SJames Wright } 1380c8564c30SJames Wright 1381c8564c30SJames Wright /** 1382c8564c30SJames Wright @brief Compute `A^T Y = X` for a `MATCEED`. 1383c8564c30SJames Wright 1384c8564c30SJames Wright Collective across MPI processes. 1385c8564c30SJames Wright 1386c8564c30SJames Wright @param[in] A `MATCEED` 1387c8564c30SJames Wright @param[in] Y Input PETSc vector 1388c8564c30SJames Wright @param[out] X Output PETSc vector 1389c8564c30SJames Wright 1390c8564c30SJames Wright @return An error code: 0 - success, otherwise - failure 1391c8564c30SJames Wright **/ 1392c8564c30SJames Wright PetscErrorCode MatMultTranspose_Ceed(Mat A, Vec Y, Vec X) { 1393c8564c30SJames Wright MatCeedContext ctx; 1394c8564c30SJames Wright 1395c8564c30SJames Wright PetscFunctionBeginUser; 1396c8564c30SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1397c8564c30SJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult_transpose, A, Y, X, 0)); 1398c8564c30SJames Wright 1399c8564c30SJames Wright { 1400c8564c30SJames Wright PetscMemType x_mem_type, y_mem_type; 1401c8564c30SJames Wright Vec X_loc, Y_loc = ctx->Y_loc_transpose; 1402c8564c30SJames Wright 1403c8564c30SJames Wright // Get local vectors 1404c8564c30SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 1405c8564c30SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 1406c8564c30SJames Wright 1407c8564c30SJames Wright // Global-to-local 1408c8564c30SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_y, Y, INSERT_VALUES, Y_loc)); 1409c8564c30SJames Wright 1410c8564c30SJames Wright // Setup libCEED vectors 1411d0593705SJames Wright PetscCall(VecReadPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 1412c8564c30SJames Wright PetscCall(VecZeroEntries(X_loc)); 1413d0593705SJames Wright PetscCall(VecPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 1414c8564c30SJames Wright 1415c8564c30SJames Wright // Apply libCEED operator 1416c8564c30SJames Wright PetscCall(PetscLogGpuTimeBegin()); 141754831c5fSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult_transpose, ctx->y_loc, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1418c8564c30SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1419c8564c30SJames Wright 1420c8564c30SJames Wright // Restore PETSc vectors 1421d0593705SJames Wright PetscCall(VecReadCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1422d0593705SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1423c8564c30SJames Wright 1424c8564c30SJames Wright // Local-to-global 1425c8564c30SJames Wright PetscCall(VecZeroEntries(X)); 1426c8564c30SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, X_loc, ADD_VALUES, X)); 1427c8564c30SJames Wright 1428c8564c30SJames Wright // Restore local vectors, as needed 1429c8564c30SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 1430c8564c30SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 1431c8564c30SJames Wright } 1432c8564c30SJames Wright 1433c8564c30SJames Wright // Log flops 1434c8564c30SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult_transpose)); 1435c8564c30SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult_transpose)); 1436c8564c30SJames Wright 1437c8564c30SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult_transpose, A, Y, X, 0)); 1438c8564c30SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1439c8564c30SJames Wright } 1440