1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors. 2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 358600ac3SJames Wright /// @file 440d80af1SJames Wright /// MatCEED implementation 558600ac3SJames Wright 658600ac3SJames Wright #include <ceed.h> 758600ac3SJames Wright #include <ceed/backend.h> 858600ac3SJames Wright #include <mat-ceed-impl.h> 958600ac3SJames Wright #include <mat-ceed.h> 1040d80af1SJames Wright #include <petsc-ceed-utils.h> 1140d80af1SJames Wright #include <petsc-ceed.h> 12000d2032SJeremy L Thompson #include <petscdm.h> 13000d2032SJeremy L Thompson #include <petscmat.h> 14000d2032SJeremy L Thompson #include <stdbool.h> 15000d2032SJeremy L Thompson #include <stdio.h> 1658600ac3SJames Wright #include <stdlib.h> 1758600ac3SJames Wright #include <string.h> 1858600ac3SJames Wright 19*b846ad1aSJames Wright #if PETSC_VERSION_LT(3, 24, 0) 20*b846ad1aSJames Wright typedef void (*MatSetOpFn)(void); 21*b846ad1aSJames Wright #else 22*b846ad1aSJames Wright typedef PetscErrorCodeFn *MatSetOpFn; 23*b846ad1aSJames Wright #endif 24*b846ad1aSJames Wright 2558600ac3SJames Wright PetscClassId MATCEED_CLASSID; 26c63b910fSJames Wright PetscLogEvent MATCEED_MULT, MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE, MATCEED_MULT_TRANSPOSE_CEEDOP, MATCEED_ASSEMBLE_DIAGONAL, 27c63b910fSJames Wright MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, MATCEED_SETUP_PBDIAGONAL, MATCEED_SETUP_PBDIAGONAL_CEEDOP, MATCEED_ASSEMBLE_PBDIAGONAL, 28c63b910fSJames Wright MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, MATCEED_SETUP_FULL, MATCEED_SETUP_FULL_CEEDOP, MATCEED_ASSEMBLE_FULL, MATCEED_ASSEMBLE_FULL_CEEDOP; 2958600ac3SJames Wright 3058600ac3SJames Wright /** 3158600ac3SJames Wright @brief Register MATCEED log events. 3258600ac3SJames Wright 3358600ac3SJames Wright Not collective across MPI processes. 3458600ac3SJames Wright 3558600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 3658600ac3SJames Wright **/ 3758600ac3SJames Wright static PetscErrorCode MatCeedRegisterLogEvents() { 3840d80af1SJames Wright static PetscBool registered = PETSC_FALSE; 3958600ac3SJames Wright 4058600ac3SJames Wright PetscFunctionBeginUser; 4158600ac3SJames Wright if (registered) PetscFunctionReturn(PETSC_SUCCESS); 42c63b910fSJames Wright PetscCall(PetscClassIdRegister("MatCEED", &MATCEED_CLASSID)); 43c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMul", MATCEED_CLASSID, &MATCEED_MULT)); 44c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulCeed", MATCEED_CLASSID, &MATCEED_MULT_CEEDOP)); 45c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulT", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE)); 46c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulTCeed", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE_CEEDOP)); 47c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmDiag", MATCEED_CLASSID, &MATCEED_ASSEMBLE_DIAGONAL)); 48c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSU", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL)); 49c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL_CEEDOP)); 50c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBD", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL)); 51c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP)); 52c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSU", MATCEED_CLASSID, &MATCEED_SETUP_FULL)); 53c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_FULL_CEEDOP)); 54c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsm", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL)); 55c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL_CEEDOP)); 5640d80af1SJames Wright registered = PETSC_TRUE; 5758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 5858600ac3SJames Wright } 5958600ac3SJames Wright 6058600ac3SJames Wright /** 6158600ac3SJames Wright @brief Assemble the point block diagonal of a `MATCEED` into a `MATAIJ` or similar. 6258600ac3SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 6358600ac3SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 6458600ac3SJames Wright 6558600ac3SJames Wright Collective across MPI processes. 6658600ac3SJames Wright 6758600ac3SJames Wright @param[in] mat_ceed `MATCEED` to assemble 6858600ac3SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 6958600ac3SJames Wright 7058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 7158600ac3SJames Wright **/ 7258600ac3SJames Wright static PetscErrorCode MatCeedAssemblePointBlockDiagonalCOO(Mat mat_ceed, Mat mat_coo) { 7358600ac3SJames Wright MatCeedContext ctx; 7458600ac3SJames Wright 7558600ac3SJames Wright PetscFunctionBeginUser; 7658600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 7758600ac3SJames Wright 7858600ac3SJames Wright // Check if COO pattern set 7958600ac3SJames Wright { 8058600ac3SJames Wright PetscInt index = -1; 8158600ac3SJames Wright 8258600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 8358600ac3SJames Wright if (ctx->mats_assembled_pbd[i] == mat_coo) index = i; 8458600ac3SJames Wright } 8558600ac3SJames Wright if (index == -1) { 8658600ac3SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 8758600ac3SJames Wright CeedInt *rows_ceed, *cols_ceed; 8858600ac3SJames Wright PetscCount num_entries; 8958600ac3SJames Wright PetscLogStage stage_amg_setup; 9058600ac3SJames Wright 9158600ac3SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 92c63b910fSJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 9358600ac3SJames Wright if (stage_amg_setup == -1) { 94c63b910fSJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 9558600ac3SJames Wright } 9658600ac3SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 97c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 98c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 9950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonalSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 100c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 101a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 102a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 10358600ac3SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 10458600ac3SJames Wright free(rows_petsc); 10558600ac3SJames Wright free(cols_petsc); 10650f50432SJames Wright if (!ctx->coo_values_pbd) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_pbd)); 10758600ac3SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_pbd * sizeof(Mat), &ctx->mats_assembled_pbd)); 10858600ac3SJames Wright ctx->mats_assembled_pbd[ctx->num_mats_assembled_pbd - 1] = mat_coo; 109c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 11058600ac3SJames Wright PetscCall(PetscLogStagePop()); 11158600ac3SJames Wright } 11258600ac3SJames Wright } 11358600ac3SJames Wright 11458600ac3SJames Wright // Assemble mat_ceed 115c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 11658600ac3SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 11758600ac3SJames Wright { 11858600ac3SJames Wright const CeedScalar *values; 119ed5c6999SJames Wright PetscMemType mem_type_petsc; 12058600ac3SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 12158600ac3SJames Wright PetscBool is_spd, is_spd_known; 12258600ac3SJames Wright 1232da92326SJames Wright PetscCall(MatGetMemTypeFromVecType(mat_coo, &mem_type_petsc)); 124ed5c6999SJames Wright mem_type = MemTypePetscToCeed(mem_type_petsc); 125c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 12650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonal(ctx->op_mult, ctx->coo_values_pbd, CEED_REQUEST_IMMEDIATE)); 127c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 12850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_pbd, mem_type, &values)); 12958600ac3SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 13058600ac3SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 13158600ac3SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 13250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_pbd, &values)); 13358600ac3SJames Wright } 13458600ac3SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 135c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 13658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 13758600ac3SJames Wright } 13858600ac3SJames Wright 13958600ac3SJames Wright /** 14058600ac3SJames Wright @brief Assemble inner `Mat` for diagonal `PC` operations 14158600ac3SJames Wright 14258600ac3SJames Wright Collective across MPI processes. 14358600ac3SJames Wright 14458600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 14558600ac3SJames Wright @param[in] use_ceed_pbd Boolean flag to use libCEED PBD assembly 14658600ac3SJames Wright @param[out] mat_inner Inner `Mat` for diagonal operations 14758600ac3SJames Wright 14858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 14958600ac3SJames Wright **/ 15058600ac3SJames Wright static PetscErrorCode MatCeedAssembleInnerBlockDiagonalMat(Mat mat_ceed, PetscBool use_ceed_pbd, Mat *mat_inner) { 15158600ac3SJames Wright MatCeedContext ctx; 15258600ac3SJames Wright 15358600ac3SJames Wright PetscFunctionBeginUser; 15458600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 15558600ac3SJames Wright if (use_ceed_pbd) { 15658600ac3SJames Wright // Check if COO pattern set 15740d80af1SJames Wright if (!ctx->mat_assembled_pbd_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_pbd_internal)); 15858600ac3SJames Wright 15958600ac3SJames Wright // Assemble mat_assembled_full_internal 16058600ac3SJames Wright PetscCall(MatCeedAssemblePointBlockDiagonalCOO(mat_ceed, ctx->mat_assembled_pbd_internal)); 16158600ac3SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_pbd_internal; 16258600ac3SJames Wright } else { 16358600ac3SJames Wright // Check if COO pattern set 16440d80af1SJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 16558600ac3SJames Wright 16658600ac3SJames Wright // Assemble mat_assembled_full_internal 16758600ac3SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 16858600ac3SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_full_internal; 16958600ac3SJames Wright } 17058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 17158600ac3SJames Wright } 17258600ac3SJames Wright 17358600ac3SJames Wright /** 174e8ff1987SJames Wright @brief Get `MATCEED` variable block diagonal for Jacobi. 175e8ff1987SJames Wright 176e8ff1987SJames Wright Collective across MPI processes. 177e8ff1987SJames Wright 178e8ff1987SJames Wright @param[in] mat_ceed `MATCEED` to invert 179e8ff1987SJames Wright @param[out] mat_vblock The variable diagonal block matrix 180e8ff1987SJames Wright 181e8ff1987SJames Wright @return An error code: 0 - success, otherwise - failure 182e8ff1987SJames Wright **/ 183e8ff1987SJames Wright static PetscErrorCode MatGetVariableBlockDiagonal_Ceed(Mat mat_ceed, Mat *mat_vblock) { 184e8ff1987SJames Wright MatCeedContext ctx; 185e8ff1987SJames Wright 186e8ff1987SJames Wright PetscFunctionBeginUser; 187e8ff1987SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 188e8ff1987SJames Wright 189e8ff1987SJames Wright // Assemble inner mat if needed 190e8ff1987SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_vpbd_valid, mat_vblock)); 191e8ff1987SJames Wright PetscCall(PetscObjectReference((PetscObject)*mat_vblock)); 192e8ff1987SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 193e8ff1987SJames Wright } 194e8ff1987SJames Wright 195e8ff1987SJames Wright /** 196e8ff1987SJames Wright @brief Get `MATCEED` block diagonal for Jacobi. 197e8ff1987SJames Wright 198e8ff1987SJames Wright Collective across MPI processes. 199e8ff1987SJames Wright 200e8ff1987SJames Wright @param[in] mat_ceed `MATCEED` to invert 201e8ff1987SJames Wright @param[out] mat_block The variable diagonal block matrix 202e8ff1987SJames Wright 203e8ff1987SJames Wright @return An error code: 0 - success, otherwise - failure 204e8ff1987SJames Wright **/ 205e8ff1987SJames Wright static PetscErrorCode MatGetBlockDiagonal_Ceed(Mat mat_ceed, Mat *mat_block) { 206e8ff1987SJames Wright MatCeedContext ctx; 207e8ff1987SJames Wright 208e8ff1987SJames Wright PetscFunctionBeginUser; 209e8ff1987SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 210e8ff1987SJames Wright 211e8ff1987SJames Wright // Assemble inner mat if needed 212e8ff1987SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_pbd_valid, mat_block)); 213e8ff1987SJames Wright PetscCall(PetscObjectReference((PetscObject)*mat_block)); 214e8ff1987SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 215e8ff1987SJames Wright } 216e8ff1987SJames Wright 217e8ff1987SJames Wright /** 218c1bdbf00SJames Wright @brief Get on-process diagonal block of `MATCEED` 219c1bdbf00SJames Wright 220c1bdbf00SJames Wright This is a block per-process of the diagonal of the global matrix. 221c1bdbf00SJames Wright This is NOT the diagonal blocks associated with the block size of the matrix (i.e. `MatSetBlockSize()` has no effect on this function). 22258600ac3SJames Wright 22358600ac3SJames Wright Collective across MPI processes. 22458600ac3SJames Wright 22558600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 22658600ac3SJames Wright @param[out] mat_block The diagonal block matrix 22758600ac3SJames Wright 22858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 22958600ac3SJames Wright **/ 23058600ac3SJames Wright static PetscErrorCode MatGetDiagonalBlock_Ceed(Mat mat_ceed, Mat *mat_block) { 23158600ac3SJames Wright MatCeedContext ctx; 23258600ac3SJames Wright 23358600ac3SJames Wright PetscFunctionBeginUser; 23458600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 23558600ac3SJames Wright 236c1bdbf00SJames Wright // Check if COO pattern set 237c1bdbf00SJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 23858600ac3SJames Wright 239c1bdbf00SJames Wright // Assemble mat_assembled_full_internal 240c1bdbf00SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 241c1bdbf00SJames Wright 242c1bdbf00SJames Wright // Get diagonal block 243c1bdbf00SJames Wright PetscCall(MatGetDiagonalBlock(ctx->mat_assembled_full_internal, mat_block)); 24458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 24558600ac3SJames Wright } 24658600ac3SJames Wright 24758600ac3SJames Wright /** 248e90c2ceeSJames Wright @brief View `MATCEED`. 249e90c2ceeSJames Wright 250e90c2ceeSJames Wright Collective across MPI processes. 251e90c2ceeSJames Wright 252e90c2ceeSJames Wright @param[in] mat_ceed `MATCEED` to view 253e90c2ceeSJames Wright @param[in] viewer The visualization context 254e90c2ceeSJames Wright 255e90c2ceeSJames Wright @return An error code: 0 - success, otherwise - failure 256e90c2ceeSJames Wright **/ 257e90c2ceeSJames Wright static PetscErrorCode MatView_Ceed(Mat mat_ceed, PetscViewer viewer) { 258e90c2ceeSJames Wright PetscBool is_ascii; 259e90c2ceeSJames Wright PetscViewerFormat format; 260000d2032SJeremy L Thompson PetscMPIInt size, rank; 261e90c2ceeSJames Wright MatCeedContext ctx; 262e90c2ceeSJames Wright 263e90c2ceeSJames Wright PetscFunctionBeginUser; 264e90c2ceeSJames Wright PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 265e90c2ceeSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 266e90c2ceeSJames Wright if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat_ceed), &viewer)); 267e90c2ceeSJames Wright 268e90c2ceeSJames Wright PetscCall(PetscViewerGetFormat(viewer, &format)); 269e90c2ceeSJames Wright PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat_ceed), &size)); 270e90c2ceeSJames Wright if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 271e90c2ceeSJames Wright 272000d2032SJeremy L Thompson PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat_ceed), &rank)); 273000d2032SJeremy L Thompson if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS); 274000d2032SJeremy L Thompson 275e90c2ceeSJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii)); 276e90c2ceeSJames Wright { 277000d2032SJeremy L Thompson PetscBool is_detailed = format == PETSC_VIEWER_ASCII_INFO_DETAIL; 278000d2032SJeremy L Thompson char rank_string[16] = {'\0'}; 279*b846ad1aSJames Wright PetscInt num_tabs = 0; 280e90c2ceeSJames Wright FILE *file; 281e90c2ceeSJames Wright 282dfdd2b92SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "MatCEED:\n")); 283537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // MatCEED 284dfdd2b92SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "Default COO MatType: %s\n", ctx->coo_mat_type)); 285000d2032SJeremy L Thompson PetscCall(PetscSNPrintf(rank_string, 16, "on Rank %d", rank)); 286000d2032SJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator Apply %s:\n", is_detailed ? rank_string : "Summary")); 287e8ff1987SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "libCEED PB Diagonal Assembly: %s\n", ctx->is_ceed_pbd_valid ? "True" : "False")); 288e8ff1987SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "libCEED VPB Diagonal Assembly: %s\n", ctx->is_ceed_vpbd_valid ? "True" : "False")); 289*b846ad1aSJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator Apply %s:\n", is_detailed ? rank_string : "Summary")); 290537ec908SJames Wright PetscCall(PetscViewerASCIIGetPointer(viewer, &file)); 291537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 292*b846ad1aSJames Wright PetscCall(PetscViewerASCIIGetTab(viewer, &num_tabs)); 293*b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult, num_tabs)); 294000d2032SJeremy L Thompson if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult, file)); 295000d2032SJeremy L Thompson else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult, file)); 296*b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult, 0)); 297537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 298e90c2ceeSJames Wright if (ctx->op_mult_transpose) { 299000d2032SJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator ApplyTranspose %s:\n", is_detailed ? rank_string : "Summary")); 300537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 301*b846ad1aSJames Wright PetscCall(PetscViewerASCIIGetTab(viewer, &num_tabs)); 302*b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult_transpose, num_tabs)); 303000d2032SJeremy L Thompson if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult_transpose, file)); 304000d2032SJeremy L Thompson else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult_transpose, file)); 305*b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult_transpose, 0)); 306537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 307e90c2ceeSJames Wright } 308537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // MatCEED 309e90c2ceeSJames Wright } 310e90c2ceeSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 311e90c2ceeSJames Wright } 312e90c2ceeSJames Wright 313*b846ad1aSJames Wright /** 314*b846ad1aSJames Wright @brief Set options for MatCeed from command-line iterface 315*b846ad1aSJames Wright 316*b846ad1aSJames Wright @note This is a PETSc interface, thus the odd signature 317*b846ad1aSJames Wright @note The name of the second parameter must be `PetscOptionsObject` due to abuse of PETSc macros 318*b846ad1aSJames Wright 319*b846ad1aSJames Wright Collective across MPI processes. 320*b846ad1aSJames Wright 321*b846ad1aSJames Wright @param[in] mat_ceed `Mat` object to set up 322*b846ad1aSJames Wright @param[in] PetscOptionsObject `PetscOptionItems` object to read options from 323*b846ad1aSJames Wright 324*b846ad1aSJames Wright @return An error code: 0 - success, otherwise - failure 325*b846ad1aSJames Wright **/ 326*b846ad1aSJames Wright static PetscErrorCode MatSetFromOptions_Ceed(Mat mat_ceed, PetscOptionItems PetscOptionsObject) { 327*b846ad1aSJames Wright MatCeedContext ctx; 328*b846ad1aSJames Wright char coo_mat_type_cl[PETSC_MAX_OPTION_NAME]; 329*b846ad1aSJames Wright PetscBool is_coo_mat_type_cl; 330*b846ad1aSJames Wright 331*b846ad1aSJames Wright PetscFunctionBegin; 332*b846ad1aSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 333*b846ad1aSJames Wright 334*b846ad1aSJames Wright PetscOptionsHeadBegin(PetscOptionsObject, "MATCEED options"); 335*b846ad1aSJames Wright // Check for specific CL coo mat type for this Mat 336*b846ad1aSJames Wright PetscCall(PetscOptionsFList("-mat_ceed_coo_mat_type", "Default MATCEED COO assembly MatType", NULL, MatList, coo_mat_type_cl, coo_mat_type_cl, 337*b846ad1aSJames Wright sizeof(coo_mat_type_cl), &is_coo_mat_type_cl)); 338*b846ad1aSJames Wright if (is_coo_mat_type_cl) { 339*b846ad1aSJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 340*b846ad1aSJames Wright PetscCall(PetscStrallocpy(coo_mat_type_cl, &ctx->coo_mat_type)); 341*b846ad1aSJames Wright } 342*b846ad1aSJames Wright // Check for COO mat reuse flag 343*b846ad1aSJames Wright PetscCall(PetscOptionsBool("-mat_ceed_coo_reuse_preallocation", 344*b846ad1aSJames Wright "Flag to allow the MatCeed to reuse existing COO preallocations, even if not set by this MatCeed", NULL, 345*b846ad1aSJames Wright ctx->coo_reuse_preallocation, &ctx->coo_reuse_preallocation, NULL)); 346*b846ad1aSJames Wright PetscOptionsHeadEnd(); 347*b846ad1aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 348*b846ad1aSJames Wright } 349*b846ad1aSJames Wright 35058600ac3SJames Wright // ----------------------------------------------------------------------------- 35158600ac3SJames Wright // MatCeed 35258600ac3SJames Wright // ----------------------------------------------------------------------------- 35358600ac3SJames Wright 35458600ac3SJames Wright /** 35558600ac3SJames Wright @brief Create PETSc `Mat` from libCEED operators. 35658600ac3SJames Wright 35758600ac3SJames Wright Collective across MPI processes. 35858600ac3SJames Wright 35958600ac3SJames Wright @param[in] dm_x Input `DM` 36058600ac3SJames Wright @param[in] dm_y Output `DM` 36158600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 36258600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 36358600ac3SJames Wright @param[out] mat New MatCeed 36458600ac3SJames Wright 36558600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 36658600ac3SJames Wright **/ 367000d2032SJeremy L Thompson PetscErrorCode MatCreateCeed(DM dm_x, DM dm_y, CeedOperator op_mult, CeedOperator op_mult_transpose, Mat *mat) { 36858600ac3SJames Wright PetscInt X_l_size, X_g_size, Y_l_size, Y_g_size; 36958600ac3SJames Wright VecType vec_type; 37058600ac3SJames Wright MatCeedContext ctx; 37158600ac3SJames Wright 37258600ac3SJames Wright PetscFunctionBeginUser; 37358600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 37458600ac3SJames Wright 37558600ac3SJames Wright // Collect context data 37658600ac3SJames Wright PetscCall(DMGetVecType(dm_x, &vec_type)); 37758600ac3SJames Wright { 37858600ac3SJames Wright Vec X; 37958600ac3SJames Wright 38058600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_x, &X)); 38158600ac3SJames Wright PetscCall(VecGetSize(X, &X_g_size)); 38258600ac3SJames Wright PetscCall(VecGetLocalSize(X, &X_l_size)); 38358600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_x, &X)); 38458600ac3SJames Wright } 38558600ac3SJames Wright if (dm_y) { 38658600ac3SJames Wright Vec Y; 38758600ac3SJames Wright 38858600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_y, &Y)); 38958600ac3SJames Wright PetscCall(VecGetSize(Y, &Y_g_size)); 39058600ac3SJames Wright PetscCall(VecGetLocalSize(Y, &Y_l_size)); 39158600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_y, &Y)); 39258600ac3SJames Wright } else { 39358600ac3SJames Wright dm_y = dm_x; 39458600ac3SJames Wright Y_g_size = X_g_size; 39558600ac3SJames Wright Y_l_size = X_l_size; 39658600ac3SJames Wright } 39740d80af1SJames Wright 39858600ac3SJames Wright // Create context 39958600ac3SJames Wright { 40058600ac3SJames Wright Vec X_loc, Y_loc_transpose = NULL; 40158600ac3SJames Wright 40258600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_x, &X_loc)); 40358600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 40458600ac3SJames Wright if (op_mult_transpose) { 40558600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_y, &Y_loc_transpose)); 40658600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc_transpose)); 40758600ac3SJames Wright } 408c63b910fSJames Wright PetscCall(MatCeedContextCreate(dm_x, dm_y, X_loc, Y_loc_transpose, op_mult, op_mult_transpose, MATCEED_MULT, MATCEED_MULT_TRANSPOSE, 409c63b910fSJames Wright MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE_CEEDOP, &ctx)); 41058600ac3SJames Wright PetscCall(VecDestroy(&X_loc)); 41158600ac3SJames Wright PetscCall(VecDestroy(&Y_loc_transpose)); 41258600ac3SJames Wright } 41358600ac3SJames Wright 41458600ac3SJames Wright // Create mat 41558600ac3SJames Wright PetscCall(MatCreateShell(PetscObjectComm((PetscObject)dm_x), Y_l_size, X_l_size, Y_g_size, X_g_size, ctx, mat)); 41658600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)*mat, MATCEED)); 41758600ac3SJames Wright // -- Set block and variable block sizes 41858600ac3SJames Wright if (dm_x == dm_y) { 41958600ac3SJames Wright MatType dm_mat_type, dm_mat_type_copy; 42058600ac3SJames Wright Mat temp_mat; 42158600ac3SJames Wright 42258600ac3SJames Wright PetscCall(DMGetMatType(dm_x, &dm_mat_type)); 42358600ac3SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 42458600ac3SJames Wright PetscCall(DMSetMatType(dm_x, MATAIJ)); 42558600ac3SJames Wright PetscCall(DMCreateMatrix(dm_x, &temp_mat)); 42658600ac3SJames Wright PetscCall(DMSetMatType(dm_x, dm_mat_type_copy)); 42758600ac3SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 42858600ac3SJames Wright 42958600ac3SJames Wright { 43058600ac3SJames Wright PetscInt block_size, num_blocks, max_vblock_size = PETSC_INT_MAX; 43158600ac3SJames Wright const PetscInt *vblock_sizes; 43258600ac3SJames Wright 43358600ac3SJames Wright // -- Get block sizes 43458600ac3SJames Wright PetscCall(MatGetBlockSize(temp_mat, &block_size)); 43558600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(temp_mat, &num_blocks, &vblock_sizes)); 43658600ac3SJames Wright { 43758600ac3SJames Wright PetscInt local_min_max[2] = {0}, global_min_max[2] = {0, PETSC_INT_MAX}; 43858600ac3SJames Wright 43958600ac3SJames Wright for (PetscInt i = 0; i < num_blocks; i++) local_min_max[1] = PetscMax(local_min_max[1], vblock_sizes[i]); 44058600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_min_max, global_min_max)); 44158600ac3SJames Wright max_vblock_size = global_min_max[1]; 44258600ac3SJames Wright } 44358600ac3SJames Wright 44458600ac3SJames Wright // -- Copy block sizes 44558600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(*mat, block_size)); 44658600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(*mat, num_blocks, (PetscInt *)vblock_sizes)); 44758600ac3SJames Wright 44858600ac3SJames Wright // -- Check libCEED compatibility 44958600ac3SJames Wright { 45058600ac3SJames Wright bool is_composite; 45158600ac3SJames Wright 45258600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_TRUE; 45358600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_TRUE; 45450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorIsComposite(op_mult, &is_composite)); 45558600ac3SJames Wright if (is_composite) { 45658600ac3SJames Wright CeedInt num_sub_operators; 45758600ac3SJames Wright CeedOperator *sub_operators; 45858600ac3SJames Wright 459da7f3a07SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorCompositeGetNumSub(op_mult, &num_sub_operators)); 460da7f3a07SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorCompositeGetSubList(op_mult, &sub_operators)); 46158600ac3SJames Wright for (CeedInt i = 0; i < num_sub_operators; i++) { 46258600ac3SJames Wright CeedInt num_bases, num_comp; 46358600ac3SJames Wright CeedBasis *active_bases; 46458600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 46558600ac3SJames Wright 46650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(sub_operators[i], &assembly_data)); 46750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 46850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 46958600ac3SJames Wright if (num_bases > 1) { 47058600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 47158600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 47258600ac3SJames Wright } 47358600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 47458600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 47558600ac3SJames Wright } 47658600ac3SJames Wright } else { 47758600ac3SJames Wright // LCOV_EXCL_START 47858600ac3SJames Wright CeedInt num_bases, num_comp; 47958600ac3SJames Wright CeedBasis *active_bases; 48058600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 48158600ac3SJames Wright 48250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(op_mult, &assembly_data)); 48350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 48450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 48558600ac3SJames Wright if (num_bases > 1) { 48658600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 48758600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 48858600ac3SJames Wright } 48958600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 49058600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 49158600ac3SJames Wright // LCOV_EXCL_STOP 49258600ac3SJames Wright } 49358600ac3SJames Wright { 49458600ac3SJames Wright PetscInt local_is_valid[2], global_is_valid[2]; 49558600ac3SJames Wright 49658600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_pbd_valid; 49758600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 49858600ac3SJames Wright ctx->is_ceed_pbd_valid = global_is_valid[0]; 49958600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_vpbd_valid; 50058600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 50158600ac3SJames Wright ctx->is_ceed_vpbd_valid = global_is_valid[0]; 50258600ac3SJames Wright } 50358600ac3SJames Wright } 50458600ac3SJames Wright } 50558600ac3SJames Wright PetscCall(MatDestroy(&temp_mat)); 50658600ac3SJames Wright } 50758600ac3SJames Wright // -- Set internal mat type 50858600ac3SJames Wright { 50958600ac3SJames Wright VecType vec_type; 51040d80af1SJames Wright MatType coo_mat_type; 51158600ac3SJames Wright 51258600ac3SJames Wright PetscCall(VecGetType(ctx->X_loc, &vec_type)); 513ed5c6999SJames Wright PetscCall(DefaultMatTypeFromVecType(vec_type, &coo_mat_type)); 51440d80af1SJames Wright PetscCall(PetscStrallocpy(coo_mat_type, &ctx->coo_mat_type)); 51558600ac3SJames Wright } 51658600ac3SJames Wright // -- Set mat operations 51767aa9f91SJames Wright PetscCall(MatShellSetContextDestroy(*mat, (PetscCtxDestroyFn *)MatCeedContextDestroy)); 518*b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_VIEW, (MatSetOpFn)MatView_Ceed)); 519*b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_MULT, (MatSetOpFn)MatMult_Ceed)); 520*b846ad1aSJames Wright if (op_mult_transpose) PetscCall(MatShellSetOperation(*mat, MATOP_MULT_TRANSPOSE, (MatSetOpFn)MatMultTranspose_Ceed)); 521*b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL, (MatSetOpFn)MatGetDiagonal_Ceed)); 522*b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL_BLOCK, (MatSetOpFn)MatGetDiagonalBlock_Ceed)); 523*b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_BLOCK_DIAGONAL, (MatSetOpFn)MatGetBlockDiagonal_Ceed)); 524*b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_VBLOCK_DIAGONAL, (MatSetOpFn)MatGetVariableBlockDiagonal_Ceed)); 525*b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_SET_FROM_OPTIONS, (MatSetOpFn)MatSetFromOptions_Ceed)); 52658600ac3SJames Wright PetscCall(MatShellSetVecType(*mat, vec_type)); 52758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 52858600ac3SJames Wright } 52958600ac3SJames Wright 53058600ac3SJames Wright /** 53158600ac3SJames Wright @brief Copy `MATCEED` into a compatible `Mat` with type `MatShell` or `MATCEED`. 53258600ac3SJames Wright 53358600ac3SJames Wright Collective across MPI processes. 53458600ac3SJames Wright 53558600ac3SJames Wright @param[in] mat_ceed `MATCEED` to copy from 53658600ac3SJames Wright @param[out] mat_other `MatShell` or `MATCEED` to copy into 53758600ac3SJames Wright 53858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 53958600ac3SJames Wright **/ 54058600ac3SJames Wright PetscErrorCode MatCeedCopy(Mat mat_ceed, Mat mat_other) { 54158600ac3SJames Wright PetscFunctionBeginUser; 54258600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 54358600ac3SJames Wright 54458600ac3SJames Wright // Check type compatibility 54558600ac3SJames Wright { 54640d80af1SJames Wright PetscBool is_matceed = PETSC_FALSE, is_matshell = PETSC_FALSE; 54758600ac3SJames Wright MatType mat_type_ceed, mat_type_other; 54858600ac3SJames Wright 54958600ac3SJames Wright PetscCall(MatGetType(mat_ceed, &mat_type_ceed)); 55040d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_ceed, MATCEED, &is_matceed)); 55140d80af1SJames Wright PetscCheck(is_matceed, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_ceed must have type " MATCEED); 55240d80af1SJames Wright PetscCall(MatGetType(mat_other, &mat_type_other)); 55340d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_other, MATCEED, &is_matceed)); 554*b846ad1aSJames Wright PetscCall(PetscStrcmp(mat_type_other, MATSHELL, &is_matshell)); 55540d80af1SJames Wright PetscCheck(is_matceed || is_matshell, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_other must have type " MATCEED " or " MATSHELL); 55658600ac3SJames Wright } 55758600ac3SJames Wright 55858600ac3SJames Wright // Check dimension compatibility 55958600ac3SJames Wright { 56058600ac3SJames 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; 56158600ac3SJames Wright 56258600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_ceed_size, &X_g_ceed_size)); 56358600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_ceed_size, &X_l_ceed_size)); 56458600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_other_size, &X_g_other_size)); 56558600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_other_size, &X_l_other_size)); 56658600ac3SJames 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) && 56758600ac3SJames Wright (X_l_ceed_size == X_l_other_size), 56858600ac3SJames Wright PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, 56958600ac3SJames Wright "mat_ceed and mat_other must have compatible sizes; found mat_ceed (Global: %" PetscInt_FMT ", %" PetscInt_FMT 57058600ac3SJames Wright "; Local: %" PetscInt_FMT ", %" PetscInt_FMT ") mat_other (Global: %" PetscInt_FMT ", %" PetscInt_FMT "; Local: %" PetscInt_FMT 57158600ac3SJames Wright ", %" PetscInt_FMT ")", 57258600ac3SJames 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); 57358600ac3SJames Wright } 57458600ac3SJames Wright 57558600ac3SJames Wright // Convert 57658600ac3SJames Wright { 57758600ac3SJames Wright VecType vec_type; 57858600ac3SJames Wright MatCeedContext ctx; 57958600ac3SJames Wright 58058600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)mat_other, MATCEED)); 58158600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 58258600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 58358600ac3SJames Wright PetscCall(MatShellSetContext(mat_other, ctx)); 58467aa9f91SJames Wright PetscCall(MatShellSetContextDestroy(mat_other, (PetscCtxDestroyFn *)MatCeedContextDestroy)); 585*b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_VIEW, (MatSetOpFn)MatView_Ceed)); 586*b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_MULT, (MatSetOpFn)MatMult_Ceed)); 587*b846ad1aSJames Wright if (ctx->op_mult_transpose) PetscCall(MatShellSetOperation(mat_other, MATOP_MULT_TRANSPOSE, (MatSetOpFn)MatMultTranspose_Ceed)); 588*b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL, (MatSetOpFn)MatGetDiagonal_Ceed)); 589*b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL_BLOCK, (MatSetOpFn)MatGetDiagonalBlock_Ceed)); 590*b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_BLOCK_DIAGONAL, (MatSetOpFn)MatGetBlockDiagonal_Ceed)); 591*b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_VBLOCK_DIAGONAL, (MatSetOpFn)MatGetVariableBlockDiagonal_Ceed)); 59258600ac3SJames Wright { 59358600ac3SJames Wright PetscInt block_size; 59458600ac3SJames Wright 59558600ac3SJames Wright PetscCall(MatGetBlockSize(mat_ceed, &block_size)); 59658600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(mat_other, block_size)); 59758600ac3SJames Wright } 59858600ac3SJames Wright { 59958600ac3SJames Wright PetscInt num_blocks; 60058600ac3SJames Wright const PetscInt *block_sizes; 60158600ac3SJames Wright 60258600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(mat_ceed, &num_blocks, &block_sizes)); 60358600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(mat_other, num_blocks, (PetscInt *)block_sizes)); 60458600ac3SJames Wright } 60558600ac3SJames Wright PetscCall(DMGetVecType(ctx->dm_x, &vec_type)); 60658600ac3SJames Wright PetscCall(MatShellSetVecType(mat_other, vec_type)); 60758600ac3SJames Wright } 60858600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 60958600ac3SJames Wright } 61058600ac3SJames Wright 61158600ac3SJames Wright /** 612ba95ebb4SJeremy L Thompson @brief Mark `CeedQFunction` data as updated and the `CeedQFunction` as requiring re-assembly for a `MatCEED`. 613000d2032SJeremy L Thompson 614000d2032SJeremy L Thompson Collective across MPI processes. 615000d2032SJeremy L Thompson 616000d2032SJeremy L Thompson @param[in] mat_ceed `MATCEED` 617000d2032SJeremy L Thompson @param[out] update_needed Boolean flag indicating `CeedQFunction` update needed 618000d2032SJeremy L Thompson 619000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 620000d2032SJeremy L Thompson **/ 621000d2032SJeremy L Thompson PetscErrorCode MatCeedSetAssemblyDataUpdateNeeded(Mat mat_ceed, PetscBool update_needed) { 622000d2032SJeremy L Thompson MatCeedContext ctx; 623000d2032SJeremy L Thompson 624000d2032SJeremy L Thompson PetscFunctionBeginUser; 625000d2032SJeremy L Thompson PetscCall(MatShellGetContext(mat_ceed, &ctx)); 626000d2032SJeremy L Thompson PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult, update_needed)); 627000d2032SJeremy L Thompson if (ctx->op_mult_transpose) { 628000d2032SJeremy L Thompson PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult_transpose, update_needed)); 629000d2032SJeremy L Thompson } 630397c0187SJeremy L Thompson if (update_needed) { 631397c0187SJeremy L Thompson PetscCall(MatAssemblyBegin(mat_ceed, MAT_FINAL_ASSEMBLY)); 632397c0187SJeremy L Thompson PetscCall(MatAssemblyEnd(mat_ceed, MAT_FINAL_ASSEMBLY)); 633397c0187SJeremy L Thompson } 634000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 635000d2032SJeremy L Thompson } 636000d2032SJeremy L Thompson 637000d2032SJeremy L Thompson /** 63840d80af1SJames Wright @brief Setup a `Mat` with the same COO pattern as a `MatCEED`. 63940d80af1SJames Wright 64040d80af1SJames Wright Collective across MPI processes. 64140d80af1SJames Wright 64240d80af1SJames Wright @param[in] mat_ceed `MATCEED` 64340d80af1SJames Wright @param[out] mat_coo Sparse `Mat` with same COO pattern 64440d80af1SJames Wright 64540d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 64640d80af1SJames Wright **/ 64740d80af1SJames Wright PetscErrorCode MatCeedCreateMatCOO(Mat mat_ceed, Mat *mat_coo) { 64840d80af1SJames Wright MatCeedContext ctx; 64940d80af1SJames Wright 65040d80af1SJames Wright PetscFunctionBeginUser; 65140d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 65240d80af1SJames Wright 65340d80af1SJames 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"); 65440d80af1SJames Wright 65540d80af1SJames Wright // Create sparse matrix 65640d80af1SJames Wright { 65740d80af1SJames Wright MatType dm_mat_type, dm_mat_type_copy; 65840d80af1SJames Wright 65940d80af1SJames Wright PetscCall(DMGetMatType(ctx->dm_x, &dm_mat_type)); 66040d80af1SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 66140d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, ctx->coo_mat_type)); 66240d80af1SJames Wright PetscCall(DMCreateMatrix(ctx->dm_x, mat_coo)); 66340d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, dm_mat_type_copy)); 66440d80af1SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 66540d80af1SJames Wright } 66640d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 66740d80af1SJames Wright } 66840d80af1SJames Wright 66940d80af1SJames Wright /** 67040d80af1SJames Wright @brief Setup the COO preallocation `MATCEED` into a `MATAIJ` or similar. 67158600ac3SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 67258600ac3SJames Wright 67358600ac3SJames Wright Collective across MPI processes. 67458600ac3SJames Wright 67558600ac3SJames Wright @param[in] mat_ceed `MATCEED` to assemble 67658600ac3SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 67758600ac3SJames Wright 67858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 67958600ac3SJames Wright **/ 68040d80af1SJames Wright PetscErrorCode MatCeedSetPreallocationCOO(Mat mat_ceed, Mat mat_coo) { 68158600ac3SJames Wright MatCeedContext ctx; 68258600ac3SJames Wright 68358600ac3SJames Wright PetscFunctionBeginUser; 68458600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 68558600ac3SJames Wright 68658600ac3SJames Wright { 68758600ac3SJames Wright PetscCount num_entries; 68858600ac3SJames Wright PetscLogStage stage_amg_setup; 689*b846ad1aSJames Wright PetscObject coo_struct; 69058600ac3SJames Wright 691c63b910fSJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 69258600ac3SJames Wright if (stage_amg_setup == -1) { 693c63b910fSJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 69458600ac3SJames Wright } 69558600ac3SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 696c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 697*b846ad1aSJames Wright PetscCall(PetscObjectQuery((PetscObject)mat_coo, "__PETSc_MatCOOStruct_Host", (PetscObject *)&coo_struct)); 698*b846ad1aSJames Wright // -- Check for existing assembly data 699*b846ad1aSJames Wright if (!ctx->coo_reuse_preallocation || !coo_struct) { 700*b846ad1aSJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 701*b846ad1aSJames Wright CeedInt *rows_ceed, *cols_ceed; 702*b846ad1aSJames Wright 703*b846ad1aSJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 704c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 70550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 706c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 707a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 708a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 70958600ac3SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 71058600ac3SJames Wright free(rows_petsc); 71158600ac3SJames Wright free(cols_petsc); 712*b846ad1aSJames Wright } else { 713*b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleGetNumEntries(ctx->op_mult, &num_entries)); 714*b846ad1aSJames Wright } 715*b846ad1aSJames Wright 71650f50432SJames Wright if (!ctx->coo_values_full) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_full)); 71758600ac3SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_full * sizeof(Mat), &ctx->mats_assembled_full)); 71858600ac3SJames Wright ctx->mats_assembled_full[ctx->num_mats_assembled_full - 1] = mat_coo; 719c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 72058600ac3SJames Wright PetscCall(PetscLogStagePop()); 72158600ac3SJames Wright } 72240d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 72340d80af1SJames Wright } 72440d80af1SJames Wright 72540d80af1SJames Wright /** 72640d80af1SJames Wright @brief Assemble a `MATCEED` into a `MATAIJ` or similar. 72740d80af1SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 72840d80af1SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 72940d80af1SJames Wright 73040d80af1SJames Wright Collective across MPI processes. 73140d80af1SJames Wright 73240d80af1SJames Wright @param[in] mat_ceed `MATCEED` to assemble 73340d80af1SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 73440d80af1SJames Wright 73540d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 73640d80af1SJames Wright **/ 73740d80af1SJames Wright PetscErrorCode MatCeedAssembleCOO(Mat mat_ceed, Mat mat_coo) { 73840d80af1SJames Wright MatCeedContext ctx; 73940d80af1SJames Wright 74040d80af1SJames Wright PetscFunctionBeginUser; 74140d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 74240d80af1SJames Wright 74340d80af1SJames Wright // Set COO pattern if needed 74440d80af1SJames Wright { 74540d80af1SJames Wright CeedInt index = -1; 74640d80af1SJames Wright 74740d80af1SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 74840d80af1SJames Wright if (ctx->mats_assembled_full[i] == mat_coo) index = i; 74940d80af1SJames Wright } 75040d80af1SJames Wright if (index == -1) PetscCall(MatCeedSetPreallocationCOO(mat_ceed, mat_coo)); 75158600ac3SJames Wright } 75258600ac3SJames Wright 75358600ac3SJames Wright // Assemble mat_ceed 754c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 75558600ac3SJames Wright { 75658600ac3SJames Wright const CeedScalar *values; 75758600ac3SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 75858600ac3SJames Wright PetscBool is_spd, is_spd_known; 759ed5c6999SJames Wright PetscMemType mem_type_petsc; 76058600ac3SJames Wright 7612da92326SJames Wright PetscCall(MatGetMemTypeFromVecType(mat_coo, &mem_type_petsc)); 762ed5c6999SJames Wright mem_type = MemTypePetscToCeed(mem_type_petsc); 763c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 76450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemble(ctx->op_mult, ctx->coo_values_full)); 765c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 76650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_full, mem_type, &values)); 76758600ac3SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 76858600ac3SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 76958600ac3SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 77050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_full, &values)); 77158600ac3SJames Wright } 772*b846ad1aSJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 77358600ac3SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 774c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 77558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 77658600ac3SJames Wright } 77758600ac3SJames Wright 77858600ac3SJames Wright /** 77940d80af1SJames Wright @brief Set the current value of a context field for a `MatCEED`. 78040d80af1SJames Wright 78140d80af1SJames Wright Not collective across MPI processes. 78240d80af1SJames Wright 78340d80af1SJames Wright @param[in,out] mat `MatCEED` 78440d80af1SJames Wright @param[in] name Name of the context field 78540d80af1SJames Wright @param[in] value New context field value 78640d80af1SJames Wright 78740d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 78840d80af1SJames Wright **/ 78940d80af1SJames Wright PetscErrorCode MatCeedSetContextDouble(Mat mat, const char *name, double value) { 79040d80af1SJames Wright PetscBool was_updated = PETSC_FALSE; 79140d80af1SJames Wright MatCeedContext ctx; 79240d80af1SJames Wright 79340d80af1SJames Wright PetscFunctionBeginUser; 79440d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 79540d80af1SJames Wright { 79640d80af1SJames Wright CeedContextFieldLabel label = NULL; 79740d80af1SJames Wright 79840d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult, name, &label)); 79940d80af1SJames Wright if (label) { 800000d2032SJeremy L Thompson double set_value = 2 * value + 1.0; 801000d2032SJeremy L Thompson 802000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 803000d2032SJeremy L Thompson if (set_value != value) { 80440d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult, label, &value)); 80540d80af1SJames Wright was_updated = PETSC_TRUE; 80640d80af1SJames Wright } 807000d2032SJeremy L Thompson } 80840d80af1SJames Wright if (ctx->op_mult_transpose) { 80940d80af1SJames Wright label = NULL; 81040d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult_transpose, name, &label)); 81140d80af1SJames Wright if (label) { 812000d2032SJeremy L Thompson double set_value = 2 * value + 1.0; 813000d2032SJeremy L Thompson 814000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 815000d2032SJeremy L Thompson if (set_value != value) { 81640d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult_transpose, label, &value)); 81740d80af1SJames Wright was_updated = PETSC_TRUE; 81840d80af1SJames Wright } 81940d80af1SJames Wright } 82040d80af1SJames Wright } 821000d2032SJeremy L Thompson } 82240d80af1SJames Wright if (was_updated) { 82340d80af1SJames Wright PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 82440d80af1SJames Wright PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 82540d80af1SJames Wright } 82640d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 82740d80af1SJames Wright } 82840d80af1SJames Wright 82940d80af1SJames Wright /** 83040d80af1SJames Wright @brief Get the current value of a context field for a `MatCEED`. 83140d80af1SJames Wright 83240d80af1SJames Wright Not collective across MPI processes. 83340d80af1SJames Wright 83440d80af1SJames Wright @param[in] mat `MatCEED` 83540d80af1SJames Wright @param[in] name Name of the context field 83640d80af1SJames Wright @param[out] value Current context field value 83740d80af1SJames Wright 83840d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 83940d80af1SJames Wright **/ 84040d80af1SJames Wright PetscErrorCode MatCeedGetContextDouble(Mat mat, const char *name, double *value) { 84140d80af1SJames Wright MatCeedContext ctx; 84240d80af1SJames Wright 84340d80af1SJames Wright PetscFunctionBeginUser; 84440d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 84540d80af1SJames Wright { 84640d80af1SJames Wright CeedContextFieldLabel label = NULL; 84740d80af1SJames Wright CeedOperator op = ctx->op_mult; 84840d80af1SJames Wright 84940d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 85040d80af1SJames Wright if (!label && ctx->op_mult_transpose) { 85140d80af1SJames Wright op = ctx->op_mult_transpose; 85240d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 85340d80af1SJames Wright } 85440d80af1SJames Wright if (label) { 85540d80af1SJames Wright PetscSizeT num_values; 85640d80af1SJames Wright const double *values_ceed; 85740d80af1SJames Wright 85840d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextDoubleRead(op, label, &num_values, &values_ceed)); 85940d80af1SJames Wright *value = values_ceed[0]; 86040d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorRestoreContextDoubleRead(op, label, &values_ceed)); 86140d80af1SJames Wright } 86240d80af1SJames Wright } 86340d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 86440d80af1SJames Wright } 86540d80af1SJames Wright 86640d80af1SJames Wright /** 867000d2032SJeremy L Thompson @brief Set the current `PetscReal` value of a context field for a `MatCEED`. 868000d2032SJeremy L Thompson 869000d2032SJeremy L Thompson Not collective across MPI processes. 870000d2032SJeremy L Thompson 871000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 872000d2032SJeremy L Thompson @param[in] name Name of the context field 873000d2032SJeremy L Thompson @param[in] value New context field value 874000d2032SJeremy L Thompson 875000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 876000d2032SJeremy L Thompson **/ 877000d2032SJeremy L Thompson PetscErrorCode MatCeedSetContextReal(Mat mat, const char *name, PetscReal value) { 878000d2032SJeremy L Thompson double value_double = value; 879000d2032SJeremy L Thompson 880000d2032SJeremy L Thompson PetscFunctionBeginUser; 881000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, name, value_double)); 882000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 883000d2032SJeremy L Thompson } 884000d2032SJeremy L Thompson 885000d2032SJeremy L Thompson /** 88651bb547fSJames Wright @brief Get the current `PetscReal` value of a context field for a `MatCEED`. 88751bb547fSJames Wright 88851bb547fSJames Wright Not collective across MPI processes. 88951bb547fSJames Wright 89051bb547fSJames Wright @param[in] mat `MatCEED` 89151bb547fSJames Wright @param[in] name Name of the context field 89251bb547fSJames Wright @param[out] value Current context field value 89351bb547fSJames Wright 89451bb547fSJames Wright @return An error code: 0 - success, otherwise - failure 89551bb547fSJames Wright **/ 89651bb547fSJames Wright PetscErrorCode MatCeedGetContextReal(Mat mat, const char *name, PetscReal *value) { 89787d3884fSJeremy L Thompson double value_double = 0.0; 89851bb547fSJames Wright 89951bb547fSJames Wright PetscFunctionBeginUser; 90051bb547fSJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &value_double)); 90151bb547fSJames Wright *value = value_double; 90251bb547fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 90351bb547fSJames Wright } 90451bb547fSJames Wright 90551bb547fSJames Wright /** 906000d2032SJeremy L Thompson @brief Set the current time for a `MatCEED`. 907000d2032SJeremy L Thompson 908000d2032SJeremy L Thompson Not collective across MPI processes. 909000d2032SJeremy L Thompson 910000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 911000d2032SJeremy L Thompson @param[in] time Current time 912000d2032SJeremy L Thompson 913000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 914000d2032SJeremy L Thompson **/ 915000d2032SJeremy L Thompson PetscErrorCode MatCeedSetTime(Mat mat, PetscReal time) { 916000d2032SJeremy L Thompson PetscFunctionBeginUser; 917000d2032SJeremy L Thompson { 918000d2032SJeremy L Thompson double time_ceed = time; 919000d2032SJeremy L Thompson 920000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "time", time_ceed)); 921000d2032SJeremy L Thompson } 922000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 923000d2032SJeremy L Thompson } 924000d2032SJeremy L Thompson 925000d2032SJeremy L Thompson /** 926000d2032SJeremy L Thompson @brief Get the current time for a `MatCEED`. 927000d2032SJeremy L Thompson 928000d2032SJeremy L Thompson Not collective across MPI processes. 929000d2032SJeremy L Thompson 930000d2032SJeremy L Thompson @param[in] mat `MatCEED` 931000d2032SJeremy L Thompson @param[out] time Current time, or -1.0 if the boundary evaluator has no time field 932000d2032SJeremy L Thompson 933000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 934000d2032SJeremy L Thompson **/ 935000d2032SJeremy L Thompson PetscErrorCode MatCeedGetTime(Mat mat, PetscReal *time) { 936000d2032SJeremy L Thompson PetscFunctionBeginUser; 937000d2032SJeremy L Thompson *time = -1.0; 938000d2032SJeremy L Thompson { 939000d2032SJeremy L Thompson double time_ceed = -1.0; 940000d2032SJeremy L Thompson 941000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, "time", &time_ceed)); 942000d2032SJeremy L Thompson *time = time_ceed; 943000d2032SJeremy L Thompson } 944000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 945000d2032SJeremy L Thompson } 946000d2032SJeremy L Thompson 947000d2032SJeremy L Thompson /** 948000d2032SJeremy L Thompson @brief Set the current time step for a `MatCEED`. 949000d2032SJeremy L Thompson 950000d2032SJeremy L Thompson Not collective across MPI processes. 951000d2032SJeremy L Thompson 952000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 953000d2032SJeremy L Thompson @param[in] dt Current time step 954000d2032SJeremy L Thompson 955000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 956000d2032SJeremy L Thompson **/ 957000d2032SJeremy L Thompson PetscErrorCode MatCeedSetDt(Mat mat, PetscReal dt) { 958000d2032SJeremy L Thompson PetscFunctionBeginUser; 959000d2032SJeremy L Thompson { 960000d2032SJeremy L Thompson double dt_ceed = dt; 961000d2032SJeremy L Thompson 962000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "dt", dt_ceed)); 963000d2032SJeremy L Thompson } 964000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 965000d2032SJeremy L Thompson } 966000d2032SJeremy L Thompson 967000d2032SJeremy L Thompson /** 968000d2032SJeremy L Thompson @brief Set the Jacobian shifts for a `MatCEED`. 969000d2032SJeremy L Thompson 970000d2032SJeremy L Thompson Not collective across MPI processes. 971000d2032SJeremy L Thompson 972000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 973000d2032SJeremy L Thompson @param[in] shift_v Velocity shift 974000d2032SJeremy L Thompson @param[in] shift_a Acceleration shift 975000d2032SJeremy L Thompson 976000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 977000d2032SJeremy L Thompson **/ 978000d2032SJeremy L Thompson PetscErrorCode MatCeedSetShifts(Mat mat, PetscReal shift_v, PetscReal shift_a) { 979000d2032SJeremy L Thompson PetscFunctionBeginUser; 980000d2032SJeremy L Thompson { 981000d2032SJeremy L Thompson double shift_v_ceed = shift_v; 982000d2032SJeremy L Thompson 983000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "shift v", shift_v_ceed)); 984000d2032SJeremy L Thompson } 985000d2032SJeremy L Thompson if (shift_a) { 986000d2032SJeremy L Thompson double shift_a_ceed = shift_a; 987000d2032SJeremy L Thompson 988000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "shift a", shift_a_ceed)); 989000d2032SJeremy L Thompson } 990000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 991000d2032SJeremy L Thompson } 992000d2032SJeremy L Thompson 993000d2032SJeremy L Thompson /** 99458600ac3SJames Wright @brief Set user context for a `MATCEED`. 99558600ac3SJames Wright 99658600ac3SJames Wright Collective across MPI processes. 99758600ac3SJames Wright 99858600ac3SJames Wright @param[in,out] mat `MATCEED` 99958600ac3SJames Wright @param[in] f The context destroy function, or NULL 100058600ac3SJames Wright @param[in] ctx User context, or NULL to unset 100158600ac3SJames Wright 100258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 100358600ac3SJames Wright **/ 100467aa9f91SJames Wright PetscErrorCode MatCeedSetContext(Mat mat, PetscCtxDestroyFn f, void *ctx) { 100558600ac3SJames Wright PetscContainer user_ctx = NULL; 100658600ac3SJames Wright 100758600ac3SJames Wright PetscFunctionBeginUser; 100858600ac3SJames Wright if (ctx) { 100958600ac3SJames Wright PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)mat), &user_ctx)); 101058600ac3SJames Wright PetscCall(PetscContainerSetPointer(user_ctx, ctx)); 101167aa9f91SJames Wright PetscCall(PetscContainerSetCtxDestroy(user_ctx, f)); 101258600ac3SJames Wright } 101358600ac3SJames Wright PetscCall(PetscObjectCompose((PetscObject)mat, "MatCeed user context", (PetscObject)user_ctx)); 101458600ac3SJames Wright PetscCall(PetscContainerDestroy(&user_ctx)); 101558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 101658600ac3SJames Wright } 101758600ac3SJames Wright 101858600ac3SJames Wright /** 101958600ac3SJames Wright @brief Retrieve the user context for a `MATCEED`. 102058600ac3SJames Wright 102158600ac3SJames Wright Collective across MPI processes. 102258600ac3SJames Wright 102358600ac3SJames Wright @param[in,out] mat `MATCEED` 102458600ac3SJames Wright @param[in] ctx User context 102558600ac3SJames Wright 102658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 102758600ac3SJames Wright **/ 102858600ac3SJames Wright PetscErrorCode MatCeedGetContext(Mat mat, void *ctx) { 102958600ac3SJames Wright PetscContainer user_ctx; 103058600ac3SJames Wright 103158600ac3SJames Wright PetscFunctionBeginUser; 103258600ac3SJames Wright PetscCall(PetscObjectQuery((PetscObject)mat, "MatCeed user context", (PetscObject *)&user_ctx)); 103358600ac3SJames Wright if (user_ctx) PetscCall(PetscContainerGetPointer(user_ctx, (void **)ctx)); 103458600ac3SJames Wright else *(void **)ctx = NULL; 103558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 103658600ac3SJames Wright } 103758600ac3SJames Wright /** 103840d80af1SJames Wright @brief Set a user defined matrix operation for a `MATCEED` matrix. 103940d80af1SJames Wright 104040d80af1SJames Wright Within each user-defined routine, the user should call `MatCeedGetContext()` to obtain the user-defined context that was set by 104140d80af1SJames Wright `MatCeedSetContext()`. 104258600ac3SJames Wright 104358600ac3SJames Wright Collective across MPI processes. 104458600ac3SJames Wright 104558600ac3SJames Wright @param[in,out] mat `MATCEED` 104640d80af1SJames Wright @param[in] op Name of the `MatOperation` 104740d80af1SJames Wright @param[in] g Function that provides the operation 104858600ac3SJames Wright 104958600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 105058600ac3SJames Wright **/ 1051*b846ad1aSJames Wright PetscErrorCode MatCeedSetOperation(Mat mat, MatOperation op, void (*g)(void)) { 105240d80af1SJames Wright PetscFunctionBeginUser; 1053*b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat, op, (MatSetOpFn)g)); 1054*b846ad1aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1055*b846ad1aSJames Wright } 1056*b846ad1aSJames Wright 1057*b846ad1aSJames Wright /** 1058*b846ad1aSJames Wright @brief Set the flag for whether the `MATCEED` should reuse a COO matrix, even if not created by this `MATCEED`. 1059*b846ad1aSJames Wright 1060*b846ad1aSJames Wright @note Only set this flag if you are certain that the COO layout is properly set on incoming matrices. 1061*b846ad1aSJames Wright 1062*b846ad1aSJames Wright Collective across MPI processes. 1063*b846ad1aSJames Wright 1064*b846ad1aSJames Wright @param[in,out] mat `MATCEED` 1065*b846ad1aSJames Wright @param[in] coo_reuse_preallocation Flag value to set 1066*b846ad1aSJames Wright 1067*b846ad1aSJames Wright @return An error code: 0 - success, otherwise - failure 1068*b846ad1aSJames Wright **/ 1069*b846ad1aSJames Wright PetscErrorCode MatCeedSetReusePreallocationCOO(Mat mat, PetscBool coo_reuse_preallocation) { 1070*b846ad1aSJames Wright MatCeedContext ctx; 1071*b846ad1aSJames Wright 1072*b846ad1aSJames Wright PetscFunctionBeginUser; 1073*b846ad1aSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1074*b846ad1aSJames Wright ctx->coo_reuse_preallocation = coo_reuse_preallocation; 1075*b846ad1aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1076*b846ad1aSJames Wright } 1077*b846ad1aSJames Wright 1078*b846ad1aSJames Wright /** 1079*b846ad1aSJames Wright @brief Gets the flag for whether the `MATCEED` should reuse a COO matrix, even if not created by this `MATCEED`. 1080*b846ad1aSJames Wright 1081*b846ad1aSJames Wright Collective across MPI processes. 1082*b846ad1aSJames Wright 1083*b846ad1aSJames Wright @param[in] mat `MATCEED` 1084*b846ad1aSJames Wright @param[in] coo_reuse_preallocation Address to store current flag value 1085*b846ad1aSJames Wright 1086*b846ad1aSJames Wright @return An error code: 0 - success, otherwise - failure 1087*b846ad1aSJames Wright **/ 1088*b846ad1aSJames Wright PetscErrorCode MatCeedGetReusePreallocationCOO(Mat mat, PetscBool *coo_reuse_preallocation) { 1089*b846ad1aSJames Wright MatCeedContext ctx; 1090*b846ad1aSJames Wright 1091*b846ad1aSJames Wright PetscFunctionBeginUser; 1092*b846ad1aSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1093*b846ad1aSJames Wright *coo_reuse_preallocation = ctx->coo_reuse_preallocation; 109440d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 109540d80af1SJames Wright } 109640d80af1SJames Wright 109740d80af1SJames Wright /** 109840d80af1SJames Wright @brief Sets the default COO matrix type as a string from the `MATCEED`. 109940d80af1SJames Wright 110040d80af1SJames Wright Collective across MPI processes. 110140d80af1SJames Wright 110240d80af1SJames Wright @param[in,out] mat `MATCEED` 110340d80af1SJames Wright @param[in] type COO `MatType` to set 110440d80af1SJames Wright 110540d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 110640d80af1SJames Wright **/ 110740d80af1SJames Wright PetscErrorCode MatCeedSetCOOMatType(Mat mat, MatType type) { 110858600ac3SJames Wright MatCeedContext ctx; 110958600ac3SJames Wright 111058600ac3SJames Wright PetscFunctionBeginUser; 111158600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 111258600ac3SJames Wright // Check if same 111358600ac3SJames Wright { 111458600ac3SJames Wright size_t len_old, len_new; 111558600ac3SJames Wright PetscBool is_same = PETSC_FALSE; 111658600ac3SJames Wright 111740d80af1SJames Wright PetscCall(PetscStrlen(ctx->coo_mat_type, &len_old)); 111858600ac3SJames Wright PetscCall(PetscStrlen(type, &len_new)); 111940d80af1SJames Wright if (len_old == len_new) PetscCall(PetscStrncmp(ctx->coo_mat_type, type, len_old, &is_same)); 112058600ac3SJames Wright if (is_same) PetscFunctionReturn(PETSC_SUCCESS); 112158600ac3SJames Wright } 112258600ac3SJames Wright // Clean up old mats in different format 112358600ac3SJames Wright // LCOV_EXCL_START 112458600ac3SJames Wright if (ctx->mat_assembled_full_internal) { 112558600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 112658600ac3SJames Wright if (ctx->mats_assembled_full[i] == ctx->mat_assembled_full_internal) { 112758600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_full; j++) { 112858600ac3SJames Wright ctx->mats_assembled_full[j - 1] = ctx->mats_assembled_full[j]; 112958600ac3SJames Wright } 113058600ac3SJames Wright ctx->num_mats_assembled_full--; 113158600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 113258600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 113358600ac3SJames Wright } 113458600ac3SJames Wright } 113558600ac3SJames Wright } 113658600ac3SJames Wright if (ctx->mat_assembled_pbd_internal) { 113758600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 113858600ac3SJames Wright if (ctx->mats_assembled_pbd[i] == ctx->mat_assembled_pbd_internal) { 113958600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_pbd; j++) { 114058600ac3SJames Wright ctx->mats_assembled_pbd[j - 1] = ctx->mats_assembled_pbd[j]; 114158600ac3SJames Wright } 114258600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 114358600ac3SJames Wright ctx->num_mats_assembled_pbd--; 114458600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 114558600ac3SJames Wright } 114658600ac3SJames Wright } 114758600ac3SJames Wright } 114840d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 114940d80af1SJames Wright PetscCall(PetscStrallocpy(type, &ctx->coo_mat_type)); 115058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 115158600ac3SJames Wright // LCOV_EXCL_STOP 115258600ac3SJames Wright } 115358600ac3SJames Wright 115458600ac3SJames Wright /** 115540d80af1SJames Wright @brief Gets the default COO matrix type as a string from the `MATCEED`. 115658600ac3SJames Wright 115758600ac3SJames Wright Collective across MPI processes. 115858600ac3SJames Wright 115958600ac3SJames Wright @param[in,out] mat `MATCEED` 116040d80af1SJames Wright @param[in] type COO `MatType` 116158600ac3SJames Wright 116258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 116358600ac3SJames Wright **/ 116440d80af1SJames Wright PetscErrorCode MatCeedGetCOOMatType(Mat mat, MatType *type) { 116558600ac3SJames Wright MatCeedContext ctx; 116658600ac3SJames Wright 116758600ac3SJames Wright PetscFunctionBeginUser; 116858600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 116940d80af1SJames Wright *type = ctx->coo_mat_type; 117058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 117158600ac3SJames Wright } 117258600ac3SJames Wright 117358600ac3SJames Wright /** 117458600ac3SJames Wright @brief Set input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 117558600ac3SJames Wright 117658600ac3SJames Wright Not collective across MPI processes. 117758600ac3SJames Wright 117858600ac3SJames Wright @param[in,out] mat `MATCEED` 117958600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 118058600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 118158600ac3SJames Wright 118258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 118358600ac3SJames Wright **/ 118458600ac3SJames Wright PetscErrorCode MatCeedSetLocalVectors(Mat mat, Vec X_loc, Vec Y_loc_transpose) { 118558600ac3SJames Wright MatCeedContext ctx; 118658600ac3SJames Wright 118758600ac3SJames Wright PetscFunctionBeginUser; 118858600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 118958600ac3SJames Wright if (X_loc) { 119058600ac3SJames Wright PetscInt len_old, len_new; 119158600ac3SJames Wright 119258600ac3SJames Wright PetscCall(VecGetSize(ctx->X_loc, &len_old)); 119358600ac3SJames Wright PetscCall(VecGetSize(X_loc, &len_new)); 119458600ac3SJames 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, 119558600ac3SJames Wright len_new, len_old); 119640d80af1SJames Wright PetscCall(VecReferenceCopy(X_loc, &ctx->X_loc)); 119758600ac3SJames Wright } 119858600ac3SJames Wright if (Y_loc_transpose) { 119958600ac3SJames Wright PetscInt len_old, len_new; 120058600ac3SJames Wright 120158600ac3SJames Wright PetscCall(VecGetSize(ctx->Y_loc_transpose, &len_old)); 120258600ac3SJames Wright PetscCall(VecGetSize(Y_loc_transpose, &len_new)); 120358600ac3SJames Wright PetscCheck(len_old == len_new, PETSC_COMM_SELF, PETSC_ERR_LIB, 120458600ac3SJames Wright "new Y_loc_transpose length %" PetscInt_FMT " should match old Y_loc_transpose length %" PetscInt_FMT, len_new, len_old); 120540d80af1SJames Wright PetscCall(VecReferenceCopy(Y_loc_transpose, &ctx->Y_loc_transpose)); 120658600ac3SJames Wright } 120758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 120858600ac3SJames Wright } 120958600ac3SJames Wright 121058600ac3SJames Wright /** 121158600ac3SJames Wright @brief Get input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 121258600ac3SJames Wright 121358600ac3SJames Wright Not collective across MPI processes. 121458600ac3SJames Wright 121558600ac3SJames Wright @param[in,out] mat `MATCEED` 121658600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 121758600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 121858600ac3SJames Wright 121958600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 122058600ac3SJames Wright **/ 122158600ac3SJames Wright PetscErrorCode MatCeedGetLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 122258600ac3SJames Wright MatCeedContext ctx; 122358600ac3SJames Wright 122458600ac3SJames Wright PetscFunctionBeginUser; 122558600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 122658600ac3SJames Wright if (X_loc) { 122740d80af1SJames Wright *X_loc = NULL; 122840d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->X_loc, X_loc)); 122958600ac3SJames Wright } 123058600ac3SJames Wright if (Y_loc_transpose) { 123140d80af1SJames Wright *Y_loc_transpose = NULL; 123240d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->Y_loc_transpose, Y_loc_transpose)); 123358600ac3SJames Wright } 123458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 123558600ac3SJames Wright } 123658600ac3SJames Wright 123758600ac3SJames Wright /** 123858600ac3SJames Wright @brief Restore input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 123958600ac3SJames Wright 124058600ac3SJames Wright Not collective across MPI processes. 124158600ac3SJames Wright 124258600ac3SJames Wright @param[in,out] mat MatCeed 124358600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 124458600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 124558600ac3SJames Wright 124658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 124758600ac3SJames Wright **/ 124858600ac3SJames Wright PetscErrorCode MatCeedRestoreLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 124958600ac3SJames Wright PetscFunctionBeginUser; 125058600ac3SJames Wright if (X_loc) PetscCall(VecDestroy(X_loc)); 125158600ac3SJames Wright if (Y_loc_transpose) PetscCall(VecDestroy(Y_loc_transpose)); 125258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 125358600ac3SJames Wright } 125458600ac3SJames Wright 125558600ac3SJames Wright /** 125658600ac3SJames Wright @brief Get libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 125758600ac3SJames Wright 125858600ac3SJames Wright Not collective across MPI processes. 125958600ac3SJames Wright 126058600ac3SJames Wright @param[in,out] mat MatCeed 126158600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 126258600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 126358600ac3SJames Wright 126458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 126558600ac3SJames Wright **/ 126658600ac3SJames Wright PetscErrorCode MatCeedGetCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 126758600ac3SJames Wright MatCeedContext ctx; 126858600ac3SJames Wright 126958600ac3SJames Wright PetscFunctionBeginUser; 127058600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 127158600ac3SJames Wright if (op_mult) { 127258600ac3SJames Wright *op_mult = NULL; 127350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult, op_mult)); 127458600ac3SJames Wright } 127558600ac3SJames Wright if (op_mult_transpose) { 127658600ac3SJames Wright *op_mult_transpose = NULL; 127750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult_transpose, op_mult_transpose)); 127858600ac3SJames Wright } 127958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 128058600ac3SJames Wright } 128158600ac3SJames Wright 128258600ac3SJames Wright /** 128358600ac3SJames Wright @brief Restore libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 128458600ac3SJames Wright 128558600ac3SJames Wright Not collective across MPI processes. 128658600ac3SJames Wright 128758600ac3SJames Wright @param[in,out] mat MatCeed 128858600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 128958600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 129058600ac3SJames Wright 129158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 129258600ac3SJames Wright **/ 129358600ac3SJames Wright PetscErrorCode MatCeedRestoreCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 129458600ac3SJames Wright MatCeedContext ctx; 129558600ac3SJames Wright 129658600ac3SJames Wright PetscFunctionBeginUser; 129758600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 129850f50432SJames Wright if (op_mult) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult)); 129950f50432SJames Wright if (op_mult_transpose) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult_transpose)); 130058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 130158600ac3SJames Wright } 130258600ac3SJames Wright 130358600ac3SJames Wright /** 130458600ac3SJames Wright @brief Set `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 130558600ac3SJames Wright 130658600ac3SJames Wright Not collective across MPI processes. 130758600ac3SJames Wright 130858600ac3SJames Wright @param[in,out] mat MatCeed 130958600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 131058600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 131158600ac3SJames Wright 131258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 131358600ac3SJames Wright **/ 131458600ac3SJames Wright PetscErrorCode MatCeedSetLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 131558600ac3SJames Wright MatCeedContext ctx; 131658600ac3SJames Wright 131758600ac3SJames Wright PetscFunctionBeginUser; 131858600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 131958600ac3SJames Wright if (log_event_mult) ctx->log_event_mult = log_event_mult; 132058600ac3SJames Wright if (log_event_mult_transpose) ctx->log_event_mult_transpose = log_event_mult_transpose; 132158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 132258600ac3SJames Wright } 132358600ac3SJames Wright 132458600ac3SJames Wright /** 132558600ac3SJames Wright @brief Get `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 132658600ac3SJames Wright 132758600ac3SJames Wright Not collective across MPI processes. 132858600ac3SJames Wright 132958600ac3SJames Wright @param[in,out] mat MatCeed 133058600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 133158600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 133258600ac3SJames Wright 133358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 133458600ac3SJames Wright **/ 133558600ac3SJames Wright PetscErrorCode MatCeedGetLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 133658600ac3SJames Wright MatCeedContext ctx; 133758600ac3SJames Wright 133858600ac3SJames Wright PetscFunctionBeginUser; 133958600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 134058600ac3SJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_mult; 134158600ac3SJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_mult_transpose; 134258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 134358600ac3SJames Wright } 134458600ac3SJames Wright 1345c63b910fSJames Wright /** 1346c63b910fSJames Wright @brief Set `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1347c63b910fSJames Wright 1348c63b910fSJames Wright Not collective across MPI processes. 1349c63b910fSJames Wright 1350c63b910fSJames Wright @param[in,out] mat MatCeed 1351c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1352c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1353c63b910fSJames Wright 1354c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1355c63b910fSJames Wright **/ 1356c63b910fSJames Wright PetscErrorCode MatCeedSetCeedOperatorLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 1357c63b910fSJames Wright MatCeedContext ctx; 1358c63b910fSJames Wright 1359c63b910fSJames Wright PetscFunctionBeginUser; 1360c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1361c63b910fSJames Wright if (log_event_mult) ctx->log_event_ceed_mult = log_event_mult; 1362c63b910fSJames Wright if (log_event_mult_transpose) ctx->log_event_ceed_mult_transpose = log_event_mult_transpose; 1363c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1364c63b910fSJames Wright } 1365c63b910fSJames Wright 1366c63b910fSJames Wright /** 1367c63b910fSJames Wright @brief Get `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1368c63b910fSJames Wright 1369c63b910fSJames Wright Not collective across MPI processes. 1370c63b910fSJames Wright 1371c63b910fSJames Wright @param[in,out] mat MatCeed 1372c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1373c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1374c63b910fSJames Wright 1375c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1376c63b910fSJames Wright **/ 1377c63b910fSJames Wright PetscErrorCode MatCeedGetCeedOperatorLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 1378c63b910fSJames Wright MatCeedContext ctx; 1379c63b910fSJames Wright 1380c63b910fSJames Wright PetscFunctionBeginUser; 1381c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1382c63b910fSJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_ceed_mult; 1383c63b910fSJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_ceed_mult_transpose; 1384c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1385c63b910fSJames Wright } 1386c63b910fSJames Wright 138758600ac3SJames Wright // ----------------------------------------------------------------------------- 138858600ac3SJames Wright // Operator context data 138958600ac3SJames Wright // ----------------------------------------------------------------------------- 139058600ac3SJames Wright 139158600ac3SJames Wright /** 139258600ac3SJames Wright @brief Setup context data for operator application. 139358600ac3SJames Wright 139458600ac3SJames Wright Collective across MPI processes. 139558600ac3SJames Wright 139658600ac3SJames Wright @param[in] dm_x Input `DM` 139758600ac3SJames Wright @param[in] dm_y Output `DM` 139858600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 139958600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 140058600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 140158600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 140258600ac3SJames Wright @param[in] log_event_mult `PetscLogEvent` for forward evaluation 140358600ac3SJames Wright @param[in] log_event_mult_transpose `PetscLogEvent` for transpose evaluation 1404c63b910fSJames Wright @param[in] log_event_ceed_mult `PetscLogEvent` for forward `CeedOperator` evaluation 1405c63b910fSJames Wright @param[in] log_event_ceed_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation 140658600ac3SJames Wright @param[out] ctx Context data for operator evaluation 140758600ac3SJames Wright 140858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 140958600ac3SJames Wright **/ 141058600ac3SJames Wright PetscErrorCode MatCeedContextCreate(DM dm_x, DM dm_y, Vec X_loc, Vec Y_loc_transpose, CeedOperator op_mult, CeedOperator op_mult_transpose, 1411c63b910fSJames Wright PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose, PetscLogEvent log_event_ceed_mult, 1412c63b910fSJames Wright PetscLogEvent log_event_ceed_mult_transpose, MatCeedContext *ctx) { 141358600ac3SJames Wright CeedSize x_loc_len, y_loc_len; 141458600ac3SJames Wright 141558600ac3SJames Wright PetscFunctionBeginUser; 141658600ac3SJames Wright // Allocate 141758600ac3SJames Wright PetscCall(PetscNew(ctx)); 141858600ac3SJames Wright (*ctx)->ref_count = 1; 141958600ac3SJames Wright 142058600ac3SJames Wright // Logging 142158600ac3SJames Wright (*ctx)->log_event_mult = log_event_mult; 142258600ac3SJames Wright (*ctx)->log_event_mult_transpose = log_event_mult_transpose; 1423c63b910fSJames Wright (*ctx)->log_event_ceed_mult = log_event_ceed_mult; 1424c63b910fSJames Wright (*ctx)->log_event_ceed_mult_transpose = log_event_ceed_mult_transpose; 142558600ac3SJames Wright 142658600ac3SJames Wright // PETSc objects 142740d80af1SJames Wright PetscCall(DMReferenceCopy(dm_x, &(*ctx)->dm_x)); 142840d80af1SJames Wright PetscCall(DMReferenceCopy(dm_y, &(*ctx)->dm_y)); 142940d80af1SJames Wright if (X_loc) PetscCall(VecReferenceCopy(X_loc, &(*ctx)->X_loc)); 143040d80af1SJames Wright if (Y_loc_transpose) PetscCall(VecReferenceCopy(Y_loc_transpose, &(*ctx)->Y_loc_transpose)); 143158600ac3SJames Wright 143258600ac3SJames Wright // Memtype 143358600ac3SJames Wright { 143458600ac3SJames Wright const PetscScalar *x; 143558600ac3SJames Wright Vec X; 143658600ac3SJames Wright 143758600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &X)); 143858600ac3SJames Wright PetscCall(VecGetArrayReadAndMemType(X, &x, &(*ctx)->mem_type)); 143958600ac3SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X, &x)); 144058600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &X)); 144158600ac3SJames Wright } 144258600ac3SJames Wright 144358600ac3SJames Wright // libCEED objects 144458600ac3SJames Wright PetscCheck(CeedOperatorGetCeed(op_mult, &(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, 144558600ac3SJames Wright "retrieving Ceed context object failed"); 144650f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetActiveVectorLengths(op_mult, &x_loc_len, &y_loc_len)); 144750f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult, &(*ctx)->op_mult)); 144850f50432SJames Wright if (op_mult_transpose) PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult_transpose, &(*ctx)->op_mult_transpose)); 1449*b846ad1aSJames Wright if (x_loc_len == -1) x_loc_len = 0; 145050f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, x_loc_len, &(*ctx)->x_loc)); 1451*b846ad1aSJames Wright if (y_loc_len == -1) y_loc_len = 0; 145250f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, y_loc_len, &(*ctx)->y_loc)); 145358600ac3SJames Wright 145458600ac3SJames Wright // Flop counting 145558600ac3SJames Wright { 145658600ac3SJames Wright CeedSize ceed_flops_estimate = 0; 145758600ac3SJames Wright 145850f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult, &ceed_flops_estimate)); 145958600ac3SJames Wright (*ctx)->flops_mult = ceed_flops_estimate; 146058600ac3SJames Wright if (op_mult_transpose) { 146150f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult_transpose, &ceed_flops_estimate)); 146258600ac3SJames Wright (*ctx)->flops_mult_transpose = ceed_flops_estimate; 146358600ac3SJames Wright } 146458600ac3SJames Wright } 146558600ac3SJames Wright 146658600ac3SJames Wright // Check sizes 146758600ac3SJames Wright if (x_loc_len > 0 || y_loc_len > 0) { 146858600ac3SJames Wright CeedSize ctx_x_loc_len, ctx_y_loc_len; 146958600ac3SJames Wright PetscInt X_loc_len, dm_x_loc_len, Y_loc_len, dm_y_loc_len; 147058600ac3SJames Wright Vec dm_X_loc, dm_Y_loc; 147158600ac3SJames Wright 147258600ac3SJames Wright // -- Input 147358600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &dm_X_loc)); 147458600ac3SJames Wright PetscCall(VecGetLocalSize(dm_X_loc, &dm_x_loc_len)); 147558600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &dm_X_loc)); 147650f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->x_loc, &ctx_x_loc_len)); 14774c17272bSJames Wright if (X_loc) { 14784c17272bSJames Wright PetscCall(VecGetLocalSize(X_loc, &X_loc_len)); 14794c17272bSJames Wright PetscCheck(X_loc_len == dm_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 14804c17272bSJames Wright "X_loc (%" PetscInt_FMT ") must match dm_x (%" PetscInt_FMT ") dimensions", X_loc_len, dm_x_loc_len); 14814c17272bSJames Wright } 14824c17272bSJames 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", 14834c17272bSJames Wright x_loc_len, dm_x_loc_len); 14844c17272bSJames 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 ")", 14854c17272bSJames Wright x_loc_len, ctx_x_loc_len); 148658600ac3SJames Wright 148758600ac3SJames Wright // -- Output 148858600ac3SJames Wright PetscCall(DMGetLocalVector(dm_y, &dm_Y_loc)); 148958600ac3SJames Wright PetscCall(VecGetLocalSize(dm_Y_loc, &dm_y_loc_len)); 149058600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_y, &dm_Y_loc)); 149150f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->y_loc, &ctx_y_loc_len)); 14924c17272bSJames 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", 14934c17272bSJames Wright ctx_y_loc_len, dm_y_loc_len); 149458600ac3SJames Wright 149558600ac3SJames Wright // -- Transpose 149658600ac3SJames Wright if (Y_loc_transpose) { 149758600ac3SJames Wright PetscCall(VecGetLocalSize(Y_loc_transpose, &Y_loc_len)); 14984c17272bSJames Wright PetscCheck(Y_loc_len == dm_y_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 14994c17272bSJames Wright "Y_loc_transpose (%" PetscInt_FMT ") must match dm_y (%" PetscInt_FMT ") dimensions", Y_loc_len, dm_y_loc_len); 150058600ac3SJames Wright } 150158600ac3SJames Wright } 150258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 150358600ac3SJames Wright } 150458600ac3SJames Wright 150558600ac3SJames Wright /** 150658600ac3SJames Wright @brief Increment reference counter for `MATCEED` context. 150758600ac3SJames Wright 150858600ac3SJames Wright Not collective across MPI processes. 150958600ac3SJames Wright 151058600ac3SJames Wright @param[in,out] ctx Context data 151158600ac3SJames Wright 151258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 151358600ac3SJames Wright **/ 151458600ac3SJames Wright PetscErrorCode MatCeedContextReference(MatCeedContext ctx) { 151558600ac3SJames Wright PetscFunctionBeginUser; 151658600ac3SJames Wright ctx->ref_count++; 151758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 151858600ac3SJames Wright } 151958600ac3SJames Wright 152058600ac3SJames Wright /** 152158600ac3SJames Wright @brief Copy reference for `MATCEED`. 152258600ac3SJames Wright Note: If `ctx_copy` is non-null, it is assumed to be a valid pointer to a `MatCeedContext`. 152358600ac3SJames Wright 152458600ac3SJames Wright Not collective across MPI processes. 152558600ac3SJames Wright 152658600ac3SJames Wright @param[in] ctx Context data 152758600ac3SJames Wright @param[out] ctx_copy Copy of pointer to context data 152858600ac3SJames Wright 152958600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 153058600ac3SJames Wright **/ 153158600ac3SJames Wright PetscErrorCode MatCeedContextReferenceCopy(MatCeedContext ctx, MatCeedContext *ctx_copy) { 153258600ac3SJames Wright PetscFunctionBeginUser; 153358600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 153467aa9f91SJames Wright PetscCall(MatCeedContextDestroy(ctx_copy)); 153558600ac3SJames Wright *ctx_copy = ctx; 153658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 153758600ac3SJames Wright } 153858600ac3SJames Wright 153958600ac3SJames Wright /** 154058600ac3SJames Wright @brief Destroy context data for operator application. 154158600ac3SJames Wright 154258600ac3SJames Wright Collective across MPI processes. 154358600ac3SJames Wright 154458600ac3SJames Wright @param[in,out] ctx Context data for operator evaluation 154558600ac3SJames Wright 154658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 154758600ac3SJames Wright **/ 154867aa9f91SJames Wright PetscErrorCode MatCeedContextDestroy(MatCeedContext *ctx) { 154958600ac3SJames Wright PetscFunctionBeginUser; 155067aa9f91SJames Wright if (!ctx || --(*ctx)->ref_count > 0) PetscFunctionReturn(PETSC_SUCCESS); 155158600ac3SJames Wright 155258600ac3SJames Wright // PETSc objects 155367aa9f91SJames Wright PetscCall(DMDestroy(&(*ctx)->dm_x)); 155467aa9f91SJames Wright PetscCall(DMDestroy(&(*ctx)->dm_y)); 155567aa9f91SJames Wright PetscCall(VecDestroy(&(*ctx)->X_loc)); 155667aa9f91SJames Wright PetscCall(VecDestroy(&(*ctx)->Y_loc_transpose)); 155767aa9f91SJames Wright PetscCall(MatDestroy(&(*ctx)->mat_assembled_full_internal)); 155867aa9f91SJames Wright PetscCall(MatDestroy(&(*ctx)->mat_assembled_pbd_internal)); 155967aa9f91SJames Wright PetscCall(PetscFree((*ctx)->coo_mat_type)); 156067aa9f91SJames Wright PetscCall(PetscFree((*ctx)->mats_assembled_full)); 156167aa9f91SJames Wright PetscCall(PetscFree((*ctx)->mats_assembled_pbd)); 156258600ac3SJames Wright 156358600ac3SJames Wright // libCEED objects 156467aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->x_loc)); 156567aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->y_loc)); 156667aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->coo_values_full)); 156767aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->coo_values_pbd)); 156867aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorDestroy(&(*ctx)->op_mult)); 156967aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorDestroy(&(*ctx)->op_mult_transpose)); 157067aa9f91SJames Wright PetscCheck(CeedDestroy(&(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, "destroying libCEED context object failed"); 157158600ac3SJames Wright 157258600ac3SJames Wright // Deallocate 157367aa9f91SJames Wright (*ctx)->is_destroyed = PETSC_TRUE; // Flag as destroyed in case someone has stale ref 157467aa9f91SJames Wright PetscCall(PetscFree(*ctx)); 157558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 157658600ac3SJames Wright } 157758600ac3SJames Wright 157858600ac3SJames Wright /** 157958600ac3SJames Wright @brief Compute the diagonal of an operator via libCEED. 158058600ac3SJames Wright 158158600ac3SJames Wright Collective across MPI processes. 158258600ac3SJames Wright 158358600ac3SJames Wright @param[in] A `MATCEED` 158458600ac3SJames Wright @param[out] D Vector holding operator diagonal 158558600ac3SJames Wright 158658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 158758600ac3SJames Wright **/ 158858600ac3SJames Wright PetscErrorCode MatGetDiagonal_Ceed(Mat A, Vec D) { 158958600ac3SJames Wright PetscMemType mem_type; 159058600ac3SJames Wright Vec D_loc; 159158600ac3SJames Wright MatCeedContext ctx; 159258600ac3SJames Wright 159358600ac3SJames Wright PetscFunctionBeginUser; 159458600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 159558600ac3SJames Wright 159658600ac3SJames Wright // Place PETSc vector in libCEED vector 1597c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 159858600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &D_loc)); 1599a7dac1d5SJames Wright PetscCall(VecPetscToCeed(D_loc, &mem_type, ctx->x_loc)); 160058600ac3SJames Wright 160158600ac3SJames Wright // Compute Diagonal 1602c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 160350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleDiagonal(ctx->op_mult, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1604c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 160558600ac3SJames Wright 160658600ac3SJames Wright // Restore PETSc vector 1607a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, mem_type, D_loc)); 160858600ac3SJames Wright 160958600ac3SJames Wright // Local-to-Global 161058600ac3SJames Wright PetscCall(VecZeroEntries(D)); 161158600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, D_loc, ADD_VALUES, D)); 161258600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &D_loc)); 1613c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 161458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 161558600ac3SJames Wright } 161658600ac3SJames Wright 161758600ac3SJames Wright /** 161858600ac3SJames Wright @brief Compute `A X = Y` for a `MATCEED`. 161958600ac3SJames Wright 162058600ac3SJames Wright Collective across MPI processes. 162158600ac3SJames Wright 162258600ac3SJames Wright @param[in] A `MATCEED` 162358600ac3SJames Wright @param[in] X Input PETSc vector 162458600ac3SJames Wright @param[out] Y Output PETSc vector 162558600ac3SJames Wright 162658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 162758600ac3SJames Wright **/ 162858600ac3SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 162958600ac3SJames Wright MatCeedContext ctx; 163058600ac3SJames Wright 163158600ac3SJames Wright PetscFunctionBeginUser; 163258600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1633c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult, A, X, Y, NULL)); 163458600ac3SJames Wright 163558600ac3SJames Wright { 163658600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 163758600ac3SJames Wright Vec X_loc = ctx->X_loc, Y_loc; 163858600ac3SJames Wright 163958600ac3SJames Wright // Get local vectors 164058600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 164158600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 164258600ac3SJames Wright 164358600ac3SJames Wright // Global-to-local 164458600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc)); 164558600ac3SJames Wright 164658600ac3SJames Wright // Setup libCEED vectors 1647a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 164858600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc)); 1649a7dac1d5SJames Wright PetscCall(VecPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 165058600ac3SJames Wright 165158600ac3SJames Wright // Apply libCEED operator 1652c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult, A, X, Y, NULL)); 1653537ec908SJames Wright PetscCall(PetscLogGpuTimeBegin()); 165450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult, ctx->x_loc, ctx->y_loc, CEED_REQUEST_IMMEDIATE)); 1655ed5c6999SJames Wright // Log flops 1656ed5c6999SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult)); 1657ed5c6999SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult)); 165858600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1659537ec908SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult, A, X, Y, NULL)); 166058600ac3SJames Wright 166158600ac3SJames Wright // Restore PETSc vectors 1662a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1663a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 166458600ac3SJames Wright 166558600ac3SJames Wright // Local-to-global 166658600ac3SJames Wright PetscCall(VecZeroEntries(Y)); 166758600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y)); 166858600ac3SJames Wright 166958600ac3SJames Wright // Restore local vectors, as needed 167058600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 167158600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 167258600ac3SJames Wright } 167358600ac3SJames Wright 1674c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult, A, X, Y, NULL)); 167558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 167658600ac3SJames Wright } 167758600ac3SJames Wright 167858600ac3SJames Wright /** 167958600ac3SJames Wright @brief Compute `A^T Y = X` for a `MATCEED`. 168058600ac3SJames Wright 168158600ac3SJames Wright Collective across MPI processes. 168258600ac3SJames Wright 168358600ac3SJames Wright @param[in] A `MATCEED` 168458600ac3SJames Wright @param[in] Y Input PETSc vector 168558600ac3SJames Wright @param[out] X Output PETSc vector 168658600ac3SJames Wright 168758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 168858600ac3SJames Wright **/ 168958600ac3SJames Wright PetscErrorCode MatMultTranspose_Ceed(Mat A, Vec Y, Vec X) { 169058600ac3SJames Wright MatCeedContext ctx; 169158600ac3SJames Wright 169258600ac3SJames Wright PetscFunctionBeginUser; 169358600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1694c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult_transpose, A, Y, X, NULL)); 169558600ac3SJames Wright 169658600ac3SJames Wright { 169758600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 169858600ac3SJames Wright Vec X_loc, Y_loc = ctx->Y_loc_transpose; 169958600ac3SJames Wright 170058600ac3SJames Wright // Get local vectors 170158600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 170258600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 170358600ac3SJames Wright 170458600ac3SJames Wright // Global-to-local 170558600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_y, Y, INSERT_VALUES, Y_loc)); 170658600ac3SJames Wright 170758600ac3SJames Wright // Setup libCEED vectors 1708a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 170958600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 1710a7dac1d5SJames Wright PetscCall(VecPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 171158600ac3SJames Wright 171258600ac3SJames Wright // Apply libCEED operator 1713c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 1714537ec908SJames Wright PetscCall(PetscLogGpuTimeBegin()); 171550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult_transpose, ctx->y_loc, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1716ed5c6999SJames Wright // Log flops 1717ed5c6999SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult_transpose)); 1718ed5c6999SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult_transpose)); 171958600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1720537ec908SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 172158600ac3SJames Wright 172258600ac3SJames Wright // Restore PETSc vectors 1723a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1724a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 172558600ac3SJames Wright 172658600ac3SJames Wright // Local-to-global 172758600ac3SJames Wright PetscCall(VecZeroEntries(X)); 172858600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, X_loc, ADD_VALUES, X)); 172958600ac3SJames Wright 173058600ac3SJames Wright // Restore local vectors, as needed 173158600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 173258600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 173358600ac3SJames Wright } 173458600ac3SJames Wright 1735c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult_transpose, A, Y, X, NULL)); 173658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 173758600ac3SJames Wright } 1738