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 19b846ad1aSJames Wright #if PETSC_VERSION_LT(3, 24, 0) 20b846ad1aSJames Wright typedef void (*MatSetOpFn)(void); 21b846ad1aSJames Wright #else 22b846ad1aSJames Wright typedef PetscErrorCodeFn *MatSetOpFn; 23b846ad1aSJames Wright #endif 24b846ad1aSJames 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 144*e338a12eSJames Wright @param[in] mat_ceed `MATCEED` to assemble block diagonal of 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 178*e338a12eSJames Wright @param[in] mat_ceed `MATCEED` to get variable block diagonal of 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 200*e338a12eSJames Wright @param[in] mat_ceed `MATCEED` to to get block diagonal of 201*e338a12eSJames Wright @param[out] mat_block The 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 /** 218*e338a12eSJames 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 225*e338a12eSJames Wright @param[in] mat_ceed `MATCEED` to get the block per-proces of 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'}; 279b846ad1aSJames Wright PetscInt num_tabs = 0; 280*e338a12eSJames Wright CeedInt prev_num_tabs; 281e90c2ceeSJames Wright FILE *file; 282e90c2ceeSJames Wright 283dfdd2b92SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "MatCEED:\n")); 284537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // MatCEED 285dfdd2b92SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "Default COO MatType: %s\n", ctx->coo_mat_type)); 286000d2032SJeremy L Thompson PetscCall(PetscSNPrintf(rank_string, 16, "on Rank %d", rank)); 287000d2032SJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator Apply %s:\n", is_detailed ? rank_string : "Summary")); 288e8ff1987SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "libCEED PB Diagonal Assembly: %s\n", ctx->is_ceed_pbd_valid ? "True" : "False")); 289e8ff1987SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "libCEED VPB Diagonal Assembly: %s\n", ctx->is_ceed_vpbd_valid ? "True" : "False")); 290b846ad1aSJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator Apply %s:\n", is_detailed ? rank_string : "Summary")); 291537ec908SJames Wright PetscCall(PetscViewerASCIIGetPointer(viewer, &file)); 292537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 293b846ad1aSJames Wright PetscCall(PetscViewerASCIIGetTab(viewer, &num_tabs)); 294b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult, num_tabs)); 295000d2032SJeremy L Thompson if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult, file)); 296000d2032SJeremy L Thompson else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult, file)); 297b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult, 0)); 298537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 299e90c2ceeSJames Wright if (ctx->op_mult_transpose) { 300000d2032SJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator ApplyTranspose %s:\n", is_detailed ? rank_string : "Summary")); 301537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 302b846ad1aSJames Wright PetscCall(PetscViewerASCIIGetTab(viewer, &num_tabs)); 303*e338a12eSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetNumViewTabs(ctx->op_mult_transpose, &prev_num_tabs)); 304b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult_transpose, num_tabs)); 305000d2032SJeremy L Thompson if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult_transpose, file)); 306000d2032SJeremy L Thompson else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult_transpose, file)); 307*e338a12eSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetNumViewTabs(ctx->op_mult_transpose, prev_num_tabs)); 308537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 309e90c2ceeSJames Wright } 310537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // MatCEED 311e90c2ceeSJames Wright } 312e90c2ceeSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 313e90c2ceeSJames Wright } 314e90c2ceeSJames Wright 315b846ad1aSJames Wright /** 316*e338a12eSJames Wright @brief Set options for MatCeed from command-line interface 317b846ad1aSJames Wright 318b846ad1aSJames Wright @note This is a PETSc interface, thus the odd signature 319b846ad1aSJames Wright @note The name of the second parameter must be `PetscOptionsObject` due to abuse of PETSc macros 320b846ad1aSJames Wright 321b846ad1aSJames Wright Collective across MPI processes. 322b846ad1aSJames Wright 323b846ad1aSJames Wright @param[in] mat_ceed `Mat` object to set up 324b846ad1aSJames Wright @param[in] PetscOptionsObject `PetscOptionItems` object to read options from 325b846ad1aSJames Wright 326b846ad1aSJames Wright @return An error code: 0 - success, otherwise - failure 327b846ad1aSJames Wright **/ 328b846ad1aSJames Wright static PetscErrorCode MatSetFromOptions_Ceed(Mat mat_ceed, PetscOptionItems PetscOptionsObject) { 329b846ad1aSJames Wright MatCeedContext ctx; 330b846ad1aSJames Wright char coo_mat_type_cl[PETSC_MAX_OPTION_NAME]; 331b846ad1aSJames Wright PetscBool is_coo_mat_type_cl; 332b846ad1aSJames Wright 333b846ad1aSJames Wright PetscFunctionBegin; 334b846ad1aSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 335b846ad1aSJames Wright 336b846ad1aSJames Wright PetscOptionsHeadBegin(PetscOptionsObject, "MATCEED options"); 337b846ad1aSJames Wright // Check for specific CL coo mat type for this Mat 338b846ad1aSJames Wright PetscCall(PetscOptionsFList("-mat_ceed_coo_mat_type", "Default MATCEED COO assembly MatType", NULL, MatList, coo_mat_type_cl, coo_mat_type_cl, 339b846ad1aSJames Wright sizeof(coo_mat_type_cl), &is_coo_mat_type_cl)); 340b846ad1aSJames Wright if (is_coo_mat_type_cl) { 341b846ad1aSJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 342b846ad1aSJames Wright PetscCall(PetscStrallocpy(coo_mat_type_cl, &ctx->coo_mat_type)); 343b846ad1aSJames Wright } 344b846ad1aSJames Wright // Check for COO mat reuse flag 345b846ad1aSJames Wright PetscCall(PetscOptionsBool("-mat_ceed_coo_reuse_preallocation", 346b846ad1aSJames Wright "Flag to allow the MatCeed to reuse existing COO preallocations, even if not set by this MatCeed", NULL, 347b846ad1aSJames Wright ctx->coo_reuse_preallocation, &ctx->coo_reuse_preallocation, NULL)); 348b846ad1aSJames Wright PetscOptionsHeadEnd(); 349b846ad1aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 350b846ad1aSJames Wright } 351b846ad1aSJames Wright 35258600ac3SJames Wright // ----------------------------------------------------------------------------- 35358600ac3SJames Wright // MatCeed 35458600ac3SJames Wright // ----------------------------------------------------------------------------- 35558600ac3SJames Wright 35658600ac3SJames Wright /** 35758600ac3SJames Wright @brief Create PETSc `Mat` from libCEED operators. 35858600ac3SJames Wright 35958600ac3SJames Wright Collective across MPI processes. 36058600ac3SJames Wright 36158600ac3SJames Wright @param[in] dm_x Input `DM` 36258600ac3SJames Wright @param[in] dm_y Output `DM` 36358600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 36458600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 36558600ac3SJames Wright @param[out] mat New MatCeed 36658600ac3SJames Wright 36758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 36858600ac3SJames Wright **/ 369000d2032SJeremy L Thompson PetscErrorCode MatCreateCeed(DM dm_x, DM dm_y, CeedOperator op_mult, CeedOperator op_mult_transpose, Mat *mat) { 37058600ac3SJames Wright PetscInt X_l_size, X_g_size, Y_l_size, Y_g_size; 37158600ac3SJames Wright VecType vec_type; 37258600ac3SJames Wright MatCeedContext ctx; 37358600ac3SJames Wright 37458600ac3SJames Wright PetscFunctionBeginUser; 37558600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 37658600ac3SJames Wright 37758600ac3SJames Wright // Collect context data 37858600ac3SJames Wright PetscCall(DMGetVecType(dm_x, &vec_type)); 37958600ac3SJames Wright { 38058600ac3SJames Wright Vec X; 38158600ac3SJames Wright 38258600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_x, &X)); 38358600ac3SJames Wright PetscCall(VecGetSize(X, &X_g_size)); 38458600ac3SJames Wright PetscCall(VecGetLocalSize(X, &X_l_size)); 38558600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_x, &X)); 38658600ac3SJames Wright } 38758600ac3SJames Wright if (dm_y) { 38858600ac3SJames Wright Vec Y; 38958600ac3SJames Wright 39058600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_y, &Y)); 39158600ac3SJames Wright PetscCall(VecGetSize(Y, &Y_g_size)); 39258600ac3SJames Wright PetscCall(VecGetLocalSize(Y, &Y_l_size)); 39358600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_y, &Y)); 39458600ac3SJames Wright } else { 39558600ac3SJames Wright dm_y = dm_x; 39658600ac3SJames Wright Y_g_size = X_g_size; 39758600ac3SJames Wright Y_l_size = X_l_size; 39858600ac3SJames Wright } 39940d80af1SJames Wright 40058600ac3SJames Wright // Create context 40158600ac3SJames Wright { 40258600ac3SJames Wright Vec X_loc, Y_loc_transpose = NULL; 40358600ac3SJames Wright 40458600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_x, &X_loc)); 40558600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 40658600ac3SJames Wright if (op_mult_transpose) { 40758600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_y, &Y_loc_transpose)); 40858600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc_transpose)); 40958600ac3SJames Wright } 410c63b910fSJames Wright PetscCall(MatCeedContextCreate(dm_x, dm_y, X_loc, Y_loc_transpose, op_mult, op_mult_transpose, MATCEED_MULT, MATCEED_MULT_TRANSPOSE, 411c63b910fSJames Wright MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE_CEEDOP, &ctx)); 41258600ac3SJames Wright PetscCall(VecDestroy(&X_loc)); 41358600ac3SJames Wright PetscCall(VecDestroy(&Y_loc_transpose)); 41458600ac3SJames Wright } 41558600ac3SJames Wright 41658600ac3SJames Wright // Create mat 41758600ac3SJames Wright PetscCall(MatCreateShell(PetscObjectComm((PetscObject)dm_x), Y_l_size, X_l_size, Y_g_size, X_g_size, ctx, mat)); 41858600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)*mat, MATCEED)); 41958600ac3SJames Wright // -- Set block and variable block sizes 42058600ac3SJames Wright if (dm_x == dm_y) { 42158600ac3SJames Wright MatType dm_mat_type, dm_mat_type_copy; 42258600ac3SJames Wright Mat temp_mat; 42358600ac3SJames Wright 42458600ac3SJames Wright PetscCall(DMGetMatType(dm_x, &dm_mat_type)); 42558600ac3SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 42658600ac3SJames Wright PetscCall(DMSetMatType(dm_x, MATAIJ)); 42758600ac3SJames Wright PetscCall(DMCreateMatrix(dm_x, &temp_mat)); 42858600ac3SJames Wright PetscCall(DMSetMatType(dm_x, dm_mat_type_copy)); 42958600ac3SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 43058600ac3SJames Wright 43158600ac3SJames Wright { 43258600ac3SJames Wright PetscInt block_size, num_blocks, max_vblock_size = PETSC_INT_MAX; 43358600ac3SJames Wright const PetscInt *vblock_sizes; 43458600ac3SJames Wright 43558600ac3SJames Wright // -- Get block sizes 43658600ac3SJames Wright PetscCall(MatGetBlockSize(temp_mat, &block_size)); 43758600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(temp_mat, &num_blocks, &vblock_sizes)); 43858600ac3SJames Wright { 43958600ac3SJames Wright PetscInt local_min_max[2] = {0}, global_min_max[2] = {0, PETSC_INT_MAX}; 44058600ac3SJames Wright 44158600ac3SJames Wright for (PetscInt i = 0; i < num_blocks; i++) local_min_max[1] = PetscMax(local_min_max[1], vblock_sizes[i]); 44258600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_min_max, global_min_max)); 44358600ac3SJames Wright max_vblock_size = global_min_max[1]; 44458600ac3SJames Wright } 44558600ac3SJames Wright 44658600ac3SJames Wright // -- Copy block sizes 44758600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(*mat, block_size)); 44858600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(*mat, num_blocks, (PetscInt *)vblock_sizes)); 44958600ac3SJames Wright 45058600ac3SJames Wright // -- Check libCEED compatibility 45158600ac3SJames Wright { 45258600ac3SJames Wright bool is_composite; 45358600ac3SJames Wright 45458600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_TRUE; 45558600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_TRUE; 45650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorIsComposite(op_mult, &is_composite)); 45758600ac3SJames Wright if (is_composite) { 45858600ac3SJames Wright CeedInt num_sub_operators; 45958600ac3SJames Wright CeedOperator *sub_operators; 46058600ac3SJames Wright 461da7f3a07SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorCompositeGetNumSub(op_mult, &num_sub_operators)); 462da7f3a07SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorCompositeGetSubList(op_mult, &sub_operators)); 46358600ac3SJames Wright for (CeedInt i = 0; i < num_sub_operators; i++) { 46458600ac3SJames Wright CeedInt num_bases, num_comp; 46558600ac3SJames Wright CeedBasis *active_bases; 46658600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 46758600ac3SJames Wright 46850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(sub_operators[i], &assembly_data)); 46950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 47050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 47158600ac3SJames Wright if (num_bases > 1) { 47258600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 47358600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 47458600ac3SJames Wright } 47558600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 47658600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 47758600ac3SJames Wright } 47858600ac3SJames Wright } else { 47958600ac3SJames Wright // LCOV_EXCL_START 48058600ac3SJames Wright CeedInt num_bases, num_comp; 48158600ac3SJames Wright CeedBasis *active_bases; 48258600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 48358600ac3SJames Wright 48450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(op_mult, &assembly_data)); 48550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 48650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 48758600ac3SJames Wright if (num_bases > 1) { 48858600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 48958600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 49058600ac3SJames Wright } 49158600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 49258600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 49358600ac3SJames Wright // LCOV_EXCL_STOP 49458600ac3SJames Wright } 49558600ac3SJames Wright { 49658600ac3SJames Wright PetscInt local_is_valid[2], global_is_valid[2]; 49758600ac3SJames Wright 49858600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_pbd_valid; 49958600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 50058600ac3SJames Wright ctx->is_ceed_pbd_valid = global_is_valid[0]; 50158600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_vpbd_valid; 50258600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 50358600ac3SJames Wright ctx->is_ceed_vpbd_valid = global_is_valid[0]; 50458600ac3SJames Wright } 50558600ac3SJames Wright } 50658600ac3SJames Wright } 50758600ac3SJames Wright PetscCall(MatDestroy(&temp_mat)); 50858600ac3SJames Wright } 50958600ac3SJames Wright // -- Set internal mat type 51058600ac3SJames Wright { 51158600ac3SJames Wright VecType vec_type; 51240d80af1SJames Wright MatType coo_mat_type; 51358600ac3SJames Wright 51458600ac3SJames Wright PetscCall(VecGetType(ctx->X_loc, &vec_type)); 515ed5c6999SJames Wright PetscCall(DefaultMatTypeFromVecType(vec_type, &coo_mat_type)); 51640d80af1SJames Wright PetscCall(PetscStrallocpy(coo_mat_type, &ctx->coo_mat_type)); 51758600ac3SJames Wright } 51858600ac3SJames Wright // -- Set mat operations 51967aa9f91SJames Wright PetscCall(MatShellSetContextDestroy(*mat, (PetscCtxDestroyFn *)MatCeedContextDestroy)); 520b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_VIEW, (MatSetOpFn)MatView_Ceed)); 521b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_MULT, (MatSetOpFn)MatMult_Ceed)); 522b846ad1aSJames Wright if (op_mult_transpose) PetscCall(MatShellSetOperation(*mat, MATOP_MULT_TRANSPOSE, (MatSetOpFn)MatMultTranspose_Ceed)); 523b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL, (MatSetOpFn)MatGetDiagonal_Ceed)); 524b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL_BLOCK, (MatSetOpFn)MatGetDiagonalBlock_Ceed)); 525b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_BLOCK_DIAGONAL, (MatSetOpFn)MatGetBlockDiagonal_Ceed)); 526b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_VBLOCK_DIAGONAL, (MatSetOpFn)MatGetVariableBlockDiagonal_Ceed)); 527b846ad1aSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_SET_FROM_OPTIONS, (MatSetOpFn)MatSetFromOptions_Ceed)); 52858600ac3SJames Wright PetscCall(MatShellSetVecType(*mat, vec_type)); 52958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 53058600ac3SJames Wright } 53158600ac3SJames Wright 53258600ac3SJames Wright /** 53358600ac3SJames Wright @brief Copy `MATCEED` into a compatible `Mat` with type `MatShell` or `MATCEED`. 53458600ac3SJames Wright 53558600ac3SJames Wright Collective across MPI processes. 53658600ac3SJames Wright 53758600ac3SJames Wright @param[in] mat_ceed `MATCEED` to copy from 53858600ac3SJames Wright @param[out] mat_other `MatShell` or `MATCEED` to copy into 53958600ac3SJames Wright 54058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 54158600ac3SJames Wright **/ 54258600ac3SJames Wright PetscErrorCode MatCeedCopy(Mat mat_ceed, Mat mat_other) { 54358600ac3SJames Wright PetscFunctionBeginUser; 54458600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 54558600ac3SJames Wright 54658600ac3SJames Wright // Check type compatibility 54758600ac3SJames Wright { 54840d80af1SJames Wright PetscBool is_matceed = PETSC_FALSE, is_matshell = PETSC_FALSE; 54958600ac3SJames Wright MatType mat_type_ceed, mat_type_other; 55058600ac3SJames Wright 55158600ac3SJames Wright PetscCall(MatGetType(mat_ceed, &mat_type_ceed)); 55240d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_ceed, MATCEED, &is_matceed)); 55340d80af1SJames Wright PetscCheck(is_matceed, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_ceed must have type " MATCEED); 55440d80af1SJames Wright PetscCall(MatGetType(mat_other, &mat_type_other)); 55540d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_other, MATCEED, &is_matceed)); 556b846ad1aSJames Wright PetscCall(PetscStrcmp(mat_type_other, MATSHELL, &is_matshell)); 55740d80af1SJames Wright PetscCheck(is_matceed || is_matshell, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_other must have type " MATCEED " or " MATSHELL); 55858600ac3SJames Wright } 55958600ac3SJames Wright 56058600ac3SJames Wright // Check dimension compatibility 56158600ac3SJames Wright { 56258600ac3SJames 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; 56358600ac3SJames Wright 56458600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_ceed_size, &X_g_ceed_size)); 56558600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_ceed_size, &X_l_ceed_size)); 56658600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_other_size, &X_g_other_size)); 56758600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_other_size, &X_l_other_size)); 56858600ac3SJames 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) && 56958600ac3SJames Wright (X_l_ceed_size == X_l_other_size), 57058600ac3SJames Wright PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, 57158600ac3SJames Wright "mat_ceed and mat_other must have compatible sizes; found mat_ceed (Global: %" PetscInt_FMT ", %" PetscInt_FMT 57258600ac3SJames Wright "; Local: %" PetscInt_FMT ", %" PetscInt_FMT ") mat_other (Global: %" PetscInt_FMT ", %" PetscInt_FMT "; Local: %" PetscInt_FMT 57358600ac3SJames Wright ", %" PetscInt_FMT ")", 57458600ac3SJames 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); 57558600ac3SJames Wright } 57658600ac3SJames Wright 57758600ac3SJames Wright // Convert 57858600ac3SJames Wright { 57958600ac3SJames Wright VecType vec_type; 58058600ac3SJames Wright MatCeedContext ctx; 58158600ac3SJames Wright 58258600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)mat_other, MATCEED)); 58358600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 58458600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 58558600ac3SJames Wright PetscCall(MatShellSetContext(mat_other, ctx)); 58667aa9f91SJames Wright PetscCall(MatShellSetContextDestroy(mat_other, (PetscCtxDestroyFn *)MatCeedContextDestroy)); 587b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_VIEW, (MatSetOpFn)MatView_Ceed)); 588b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_MULT, (MatSetOpFn)MatMult_Ceed)); 589b846ad1aSJames Wright if (ctx->op_mult_transpose) PetscCall(MatShellSetOperation(mat_other, MATOP_MULT_TRANSPOSE, (MatSetOpFn)MatMultTranspose_Ceed)); 590b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL, (MatSetOpFn)MatGetDiagonal_Ceed)); 591b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL_BLOCK, (MatSetOpFn)MatGetDiagonalBlock_Ceed)); 592b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_BLOCK_DIAGONAL, (MatSetOpFn)MatGetBlockDiagonal_Ceed)); 593b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_VBLOCK_DIAGONAL, (MatSetOpFn)MatGetVariableBlockDiagonal_Ceed)); 59458600ac3SJames Wright { 59558600ac3SJames Wright PetscInt block_size; 59658600ac3SJames Wright 59758600ac3SJames Wright PetscCall(MatGetBlockSize(mat_ceed, &block_size)); 59858600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(mat_other, block_size)); 59958600ac3SJames Wright } 60058600ac3SJames Wright { 60158600ac3SJames Wright PetscInt num_blocks; 60258600ac3SJames Wright const PetscInt *block_sizes; 60358600ac3SJames Wright 60458600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(mat_ceed, &num_blocks, &block_sizes)); 60558600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(mat_other, num_blocks, (PetscInt *)block_sizes)); 60658600ac3SJames Wright } 60758600ac3SJames Wright PetscCall(DMGetVecType(ctx->dm_x, &vec_type)); 60858600ac3SJames Wright PetscCall(MatShellSetVecType(mat_other, vec_type)); 60958600ac3SJames Wright } 61058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 61158600ac3SJames Wright } 61258600ac3SJames Wright 61358600ac3SJames Wright /** 614ba95ebb4SJeremy L Thompson @brief Mark `CeedQFunction` data as updated and the `CeedQFunction` as requiring re-assembly for a `MatCEED`. 615000d2032SJeremy L Thompson 616000d2032SJeremy L Thompson Collective across MPI processes. 617000d2032SJeremy L Thompson 618000d2032SJeremy L Thompson @param[in] mat_ceed `MATCEED` 619000d2032SJeremy L Thompson @param[out] update_needed Boolean flag indicating `CeedQFunction` update needed 620000d2032SJeremy L Thompson 621000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 622000d2032SJeremy L Thompson **/ 623000d2032SJeremy L Thompson PetscErrorCode MatCeedSetAssemblyDataUpdateNeeded(Mat mat_ceed, PetscBool update_needed) { 624000d2032SJeremy L Thompson MatCeedContext ctx; 625000d2032SJeremy L Thompson 626000d2032SJeremy L Thompson PetscFunctionBeginUser; 627000d2032SJeremy L Thompson PetscCall(MatShellGetContext(mat_ceed, &ctx)); 628000d2032SJeremy L Thompson PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult, update_needed)); 629000d2032SJeremy L Thompson if (ctx->op_mult_transpose) { 630000d2032SJeremy L Thompson PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult_transpose, update_needed)); 631000d2032SJeremy L Thompson } 632397c0187SJeremy L Thompson if (update_needed) { 633397c0187SJeremy L Thompson PetscCall(MatAssemblyBegin(mat_ceed, MAT_FINAL_ASSEMBLY)); 634397c0187SJeremy L Thompson PetscCall(MatAssemblyEnd(mat_ceed, MAT_FINAL_ASSEMBLY)); 635397c0187SJeremy L Thompson } 636000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 637000d2032SJeremy L Thompson } 638000d2032SJeremy L Thompson 639000d2032SJeremy L Thompson /** 64040d80af1SJames Wright @brief Setup a `Mat` with the same COO pattern as a `MatCEED`. 64140d80af1SJames Wright 64240d80af1SJames Wright Collective across MPI processes. 64340d80af1SJames Wright 64440d80af1SJames Wright @param[in] mat_ceed `MATCEED` 64540d80af1SJames Wright @param[out] mat_coo Sparse `Mat` with same COO pattern 64640d80af1SJames Wright 64740d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 64840d80af1SJames Wright **/ 64940d80af1SJames Wright PetscErrorCode MatCeedCreateMatCOO(Mat mat_ceed, Mat *mat_coo) { 65040d80af1SJames Wright MatCeedContext ctx; 65140d80af1SJames Wright 65240d80af1SJames Wright PetscFunctionBeginUser; 65340d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 65440d80af1SJames Wright 65540d80af1SJames 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"); 65640d80af1SJames Wright 65740d80af1SJames Wright // Create sparse matrix 65840d80af1SJames Wright { 65940d80af1SJames Wright MatType dm_mat_type, dm_mat_type_copy; 66040d80af1SJames Wright 66140d80af1SJames Wright PetscCall(DMGetMatType(ctx->dm_x, &dm_mat_type)); 66240d80af1SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 66340d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, ctx->coo_mat_type)); 66440d80af1SJames Wright PetscCall(DMCreateMatrix(ctx->dm_x, mat_coo)); 66540d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, dm_mat_type_copy)); 66640d80af1SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 66740d80af1SJames Wright } 66840d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 66940d80af1SJames Wright } 67040d80af1SJames Wright 67140d80af1SJames Wright /** 67240d80af1SJames Wright @brief Setup the COO preallocation `MATCEED` into a `MATAIJ` or similar. 67358600ac3SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 67458600ac3SJames Wright 67558600ac3SJames Wright Collective across MPI processes. 67658600ac3SJames Wright 67758600ac3SJames Wright @param[in] mat_ceed `MATCEED` to assemble 67858600ac3SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 67958600ac3SJames Wright 68058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 68158600ac3SJames Wright **/ 68240d80af1SJames Wright PetscErrorCode MatCeedSetPreallocationCOO(Mat mat_ceed, Mat mat_coo) { 68358600ac3SJames Wright MatCeedContext ctx; 68458600ac3SJames Wright 68558600ac3SJames Wright PetscFunctionBeginUser; 68658600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 68758600ac3SJames Wright 68858600ac3SJames Wright { 68958600ac3SJames Wright PetscCount num_entries; 69058600ac3SJames Wright PetscLogStage stage_amg_setup; 691b846ad1aSJames Wright PetscObject coo_struct; 69258600ac3SJames Wright 693c63b910fSJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 69458600ac3SJames Wright if (stage_amg_setup == -1) { 695c63b910fSJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 69658600ac3SJames Wright } 69758600ac3SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 698c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 699b846ad1aSJames Wright PetscCall(PetscObjectQuery((PetscObject)mat_coo, "__PETSc_MatCOOStruct_Host", (PetscObject *)&coo_struct)); 700b846ad1aSJames Wright // -- Check for existing assembly data 701b846ad1aSJames Wright if (!ctx->coo_reuse_preallocation || !coo_struct) { 702b846ad1aSJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 703b846ad1aSJames Wright CeedInt *rows_ceed, *cols_ceed; 704b846ad1aSJames Wright 705b846ad1aSJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 706c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 70750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 708c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 709a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 710a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 71158600ac3SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 71258600ac3SJames Wright free(rows_petsc); 71358600ac3SJames Wright free(cols_petsc); 714b846ad1aSJames Wright } else { 715b846ad1aSJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleGetNumEntries(ctx->op_mult, &num_entries)); 716b846ad1aSJames Wright } 717b846ad1aSJames Wright 71850f50432SJames Wright if (!ctx->coo_values_full) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_full)); 71958600ac3SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_full * sizeof(Mat), &ctx->mats_assembled_full)); 72058600ac3SJames Wright ctx->mats_assembled_full[ctx->num_mats_assembled_full - 1] = mat_coo; 721c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 72258600ac3SJames Wright PetscCall(PetscLogStagePop()); 72358600ac3SJames Wright } 72440d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 72540d80af1SJames Wright } 72640d80af1SJames Wright 72740d80af1SJames Wright /** 72840d80af1SJames Wright @brief Assemble a `MATCEED` into a `MATAIJ` or similar. 72940d80af1SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 73040d80af1SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 73140d80af1SJames Wright 73240d80af1SJames Wright Collective across MPI processes. 73340d80af1SJames Wright 73440d80af1SJames Wright @param[in] mat_ceed `MATCEED` to assemble 73540d80af1SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 73640d80af1SJames Wright 73740d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 73840d80af1SJames Wright **/ 73940d80af1SJames Wright PetscErrorCode MatCeedAssembleCOO(Mat mat_ceed, Mat mat_coo) { 74040d80af1SJames Wright MatCeedContext ctx; 74140d80af1SJames Wright 74240d80af1SJames Wright PetscFunctionBeginUser; 74340d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 74440d80af1SJames Wright 74540d80af1SJames Wright // Set COO pattern if needed 74640d80af1SJames Wright { 74740d80af1SJames Wright CeedInt index = -1; 74840d80af1SJames Wright 74940d80af1SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 75040d80af1SJames Wright if (ctx->mats_assembled_full[i] == mat_coo) index = i; 75140d80af1SJames Wright } 75240d80af1SJames Wright if (index == -1) PetscCall(MatCeedSetPreallocationCOO(mat_ceed, mat_coo)); 75358600ac3SJames Wright } 75458600ac3SJames Wright 75558600ac3SJames Wright // Assemble mat_ceed 756c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 75758600ac3SJames Wright { 75858600ac3SJames Wright const CeedScalar *values; 75958600ac3SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 76058600ac3SJames Wright PetscBool is_spd, is_spd_known; 761ed5c6999SJames Wright PetscMemType mem_type_petsc; 76258600ac3SJames Wright 7632da92326SJames Wright PetscCall(MatGetMemTypeFromVecType(mat_coo, &mem_type_petsc)); 764ed5c6999SJames Wright mem_type = MemTypePetscToCeed(mem_type_petsc); 765c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 76650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemble(ctx->op_mult, ctx->coo_values_full)); 767c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 76850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_full, mem_type, &values)); 76958600ac3SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 77058600ac3SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 77158600ac3SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 77250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_full, &values)); 77358600ac3SJames Wright } 774b846ad1aSJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 77558600ac3SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 776c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 77758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 77858600ac3SJames Wright } 77958600ac3SJames Wright 78058600ac3SJames Wright /** 78140d80af1SJames Wright @brief Set the current value of a context field for a `MatCEED`. 78240d80af1SJames Wright 78340d80af1SJames Wright Not collective across MPI processes. 78440d80af1SJames Wright 78540d80af1SJames Wright @param[in,out] mat `MatCEED` 78640d80af1SJames Wright @param[in] name Name of the context field 78740d80af1SJames Wright @param[in] value New context field value 78840d80af1SJames Wright 78940d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 79040d80af1SJames Wright **/ 79140d80af1SJames Wright PetscErrorCode MatCeedSetContextDouble(Mat mat, const char *name, double value) { 79240d80af1SJames Wright PetscBool was_updated = PETSC_FALSE; 79340d80af1SJames Wright MatCeedContext ctx; 79440d80af1SJames Wright 79540d80af1SJames Wright PetscFunctionBeginUser; 79640d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 79740d80af1SJames Wright { 79840d80af1SJames Wright CeedContextFieldLabel label = NULL; 79940d80af1SJames Wright 80040d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult, name, &label)); 80140d80af1SJames Wright if (label) { 802000d2032SJeremy L Thompson double set_value = 2 * value + 1.0; 803000d2032SJeremy L Thompson 804000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 805000d2032SJeremy L Thompson if (set_value != value) { 80640d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult, label, &value)); 80740d80af1SJames Wright was_updated = PETSC_TRUE; 80840d80af1SJames Wright } 809000d2032SJeremy L Thompson } 81040d80af1SJames Wright if (ctx->op_mult_transpose) { 81140d80af1SJames Wright label = NULL; 81240d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult_transpose, name, &label)); 81340d80af1SJames Wright if (label) { 814000d2032SJeremy L Thompson double set_value = 2 * value + 1.0; 815000d2032SJeremy L Thompson 816000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 817000d2032SJeremy L Thompson if (set_value != value) { 81840d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult_transpose, label, &value)); 81940d80af1SJames Wright was_updated = PETSC_TRUE; 82040d80af1SJames Wright } 82140d80af1SJames Wright } 82240d80af1SJames Wright } 823000d2032SJeremy L Thompson } 82440d80af1SJames Wright if (was_updated) { 82540d80af1SJames Wright PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 82640d80af1SJames Wright PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 82740d80af1SJames Wright } 82840d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 82940d80af1SJames Wright } 83040d80af1SJames Wright 83140d80af1SJames Wright /** 83240d80af1SJames Wright @brief Get the current value of a context field for a `MatCEED`. 83340d80af1SJames Wright 83440d80af1SJames Wright Not collective across MPI processes. 83540d80af1SJames Wright 83640d80af1SJames Wright @param[in] mat `MatCEED` 83740d80af1SJames Wright @param[in] name Name of the context field 83840d80af1SJames Wright @param[out] value Current context field value 83940d80af1SJames Wright 84040d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 84140d80af1SJames Wright **/ 84240d80af1SJames Wright PetscErrorCode MatCeedGetContextDouble(Mat mat, const char *name, double *value) { 84340d80af1SJames Wright MatCeedContext ctx; 84440d80af1SJames Wright 84540d80af1SJames Wright PetscFunctionBeginUser; 84640d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 84740d80af1SJames Wright { 84840d80af1SJames Wright CeedContextFieldLabel label = NULL; 84940d80af1SJames Wright CeedOperator op = ctx->op_mult; 85040d80af1SJames Wright 85140d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 85240d80af1SJames Wright if (!label && ctx->op_mult_transpose) { 85340d80af1SJames Wright op = ctx->op_mult_transpose; 85440d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 85540d80af1SJames Wright } 85640d80af1SJames Wright if (label) { 85740d80af1SJames Wright PetscSizeT num_values; 85840d80af1SJames Wright const double *values_ceed; 85940d80af1SJames Wright 86040d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextDoubleRead(op, label, &num_values, &values_ceed)); 86140d80af1SJames Wright *value = values_ceed[0]; 86240d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorRestoreContextDoubleRead(op, label, &values_ceed)); 86340d80af1SJames Wright } 86440d80af1SJames Wright } 86540d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 86640d80af1SJames Wright } 86740d80af1SJames Wright 86840d80af1SJames Wright /** 869000d2032SJeremy L Thompson @brief Set the current `PetscReal` value of a context field for a `MatCEED`. 870000d2032SJeremy L Thompson 871000d2032SJeremy L Thompson Not collective across MPI processes. 872000d2032SJeremy L Thompson 873000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 874000d2032SJeremy L Thompson @param[in] name Name of the context field 875000d2032SJeremy L Thompson @param[in] value New context field value 876000d2032SJeremy L Thompson 877000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 878000d2032SJeremy L Thompson **/ 879000d2032SJeremy L Thompson PetscErrorCode MatCeedSetContextReal(Mat mat, const char *name, PetscReal value) { 880000d2032SJeremy L Thompson double value_double = value; 881000d2032SJeremy L Thompson 882000d2032SJeremy L Thompson PetscFunctionBeginUser; 883000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, name, value_double)); 884000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 885000d2032SJeremy L Thompson } 886000d2032SJeremy L Thompson 887000d2032SJeremy L Thompson /** 88851bb547fSJames Wright @brief Get the current `PetscReal` value of a context field for a `MatCEED`. 88951bb547fSJames Wright 89051bb547fSJames Wright Not collective across MPI processes. 89151bb547fSJames Wright 89251bb547fSJames Wright @param[in] mat `MatCEED` 89351bb547fSJames Wright @param[in] name Name of the context field 89451bb547fSJames Wright @param[out] value Current context field value 89551bb547fSJames Wright 89651bb547fSJames Wright @return An error code: 0 - success, otherwise - failure 89751bb547fSJames Wright **/ 89851bb547fSJames Wright PetscErrorCode MatCeedGetContextReal(Mat mat, const char *name, PetscReal *value) { 89987d3884fSJeremy L Thompson double value_double = 0.0; 90051bb547fSJames Wright 90151bb547fSJames Wright PetscFunctionBeginUser; 90251bb547fSJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &value_double)); 90351bb547fSJames Wright *value = value_double; 90451bb547fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 90551bb547fSJames Wright } 90651bb547fSJames Wright 90751bb547fSJames Wright /** 908000d2032SJeremy L Thompson @brief Set the current time for a `MatCEED`. 909000d2032SJeremy L Thompson 910000d2032SJeremy L Thompson Not collective across MPI processes. 911000d2032SJeremy L Thompson 912000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 913000d2032SJeremy L Thompson @param[in] time Current time 914000d2032SJeremy L Thompson 915000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 916000d2032SJeremy L Thompson **/ 917000d2032SJeremy L Thompson PetscErrorCode MatCeedSetTime(Mat mat, PetscReal time) { 918000d2032SJeremy L Thompson PetscFunctionBeginUser; 919000d2032SJeremy L Thompson { 920000d2032SJeremy L Thompson double time_ceed = time; 921000d2032SJeremy L Thompson 922000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "time", time_ceed)); 923000d2032SJeremy L Thompson } 924000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 925000d2032SJeremy L Thompson } 926000d2032SJeremy L Thompson 927000d2032SJeremy L Thompson /** 928000d2032SJeremy L Thompson @brief Get the current time for a `MatCEED`. 929000d2032SJeremy L Thompson 930000d2032SJeremy L Thompson Not collective across MPI processes. 931000d2032SJeremy L Thompson 932000d2032SJeremy L Thompson @param[in] mat `MatCEED` 933000d2032SJeremy L Thompson @param[out] time Current time, or -1.0 if the boundary evaluator has no time field 934000d2032SJeremy L Thompson 935000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 936000d2032SJeremy L Thompson **/ 937000d2032SJeremy L Thompson PetscErrorCode MatCeedGetTime(Mat mat, PetscReal *time) { 938000d2032SJeremy L Thompson PetscFunctionBeginUser; 939000d2032SJeremy L Thompson *time = -1.0; 940000d2032SJeremy L Thompson { 941000d2032SJeremy L Thompson double time_ceed = -1.0; 942000d2032SJeremy L Thompson 943000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, "time", &time_ceed)); 944000d2032SJeremy L Thompson *time = time_ceed; 945000d2032SJeremy L Thompson } 946000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 947000d2032SJeremy L Thompson } 948000d2032SJeremy L Thompson 949000d2032SJeremy L Thompson /** 950000d2032SJeremy L Thompson @brief Set the current time step for a `MatCEED`. 951000d2032SJeremy L Thompson 952000d2032SJeremy L Thompson Not collective across MPI processes. 953000d2032SJeremy L Thompson 954000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 955000d2032SJeremy L Thompson @param[in] dt Current time step 956000d2032SJeremy L Thompson 957000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 958000d2032SJeremy L Thompson **/ 959000d2032SJeremy L Thompson PetscErrorCode MatCeedSetDt(Mat mat, PetscReal dt) { 960000d2032SJeremy L Thompson PetscFunctionBeginUser; 961000d2032SJeremy L Thompson { 962000d2032SJeremy L Thompson double dt_ceed = dt; 963000d2032SJeremy L Thompson 964000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "dt", dt_ceed)); 965000d2032SJeremy L Thompson } 966000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 967000d2032SJeremy L Thompson } 968000d2032SJeremy L Thompson 969000d2032SJeremy L Thompson /** 970000d2032SJeremy L Thompson @brief Set the Jacobian shifts for a `MatCEED`. 971000d2032SJeremy L Thompson 972000d2032SJeremy L Thompson Not collective across MPI processes. 973000d2032SJeremy L Thompson 974000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 975000d2032SJeremy L Thompson @param[in] shift_v Velocity shift 976000d2032SJeremy L Thompson @param[in] shift_a Acceleration shift 977000d2032SJeremy L Thompson 978000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 979000d2032SJeremy L Thompson **/ 980000d2032SJeremy L Thompson PetscErrorCode MatCeedSetShifts(Mat mat, PetscReal shift_v, PetscReal shift_a) { 981000d2032SJeremy L Thompson PetscFunctionBeginUser; 982000d2032SJeremy L Thompson { 983000d2032SJeremy L Thompson double shift_v_ceed = shift_v; 984000d2032SJeremy L Thompson 985000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "shift v", shift_v_ceed)); 986000d2032SJeremy L Thompson } 987000d2032SJeremy L Thompson if (shift_a) { 988000d2032SJeremy L Thompson double shift_a_ceed = shift_a; 989000d2032SJeremy L Thompson 990000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "shift a", shift_a_ceed)); 991000d2032SJeremy L Thompson } 992000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 993000d2032SJeremy L Thompson } 994000d2032SJeremy L Thompson 995000d2032SJeremy L Thompson /** 99658600ac3SJames Wright @brief Set user context for a `MATCEED`. 99758600ac3SJames Wright 99858600ac3SJames Wright Collective across MPI processes. 99958600ac3SJames Wright 100058600ac3SJames Wright @param[in,out] mat `MATCEED` 100158600ac3SJames Wright @param[in] f The context destroy function, or NULL 100258600ac3SJames Wright @param[in] ctx User context, or NULL to unset 100358600ac3SJames Wright 100458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 100558600ac3SJames Wright **/ 100667aa9f91SJames Wright PetscErrorCode MatCeedSetContext(Mat mat, PetscCtxDestroyFn f, void *ctx) { 100758600ac3SJames Wright PetscContainer user_ctx = NULL; 100858600ac3SJames Wright 100958600ac3SJames Wright PetscFunctionBeginUser; 101058600ac3SJames Wright if (ctx) { 101158600ac3SJames Wright PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)mat), &user_ctx)); 101258600ac3SJames Wright PetscCall(PetscContainerSetPointer(user_ctx, ctx)); 101367aa9f91SJames Wright PetscCall(PetscContainerSetCtxDestroy(user_ctx, f)); 101458600ac3SJames Wright } 101558600ac3SJames Wright PetscCall(PetscObjectCompose((PetscObject)mat, "MatCeed user context", (PetscObject)user_ctx)); 101658600ac3SJames Wright PetscCall(PetscContainerDestroy(&user_ctx)); 101758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 101858600ac3SJames Wright } 101958600ac3SJames Wright 102058600ac3SJames Wright /** 102158600ac3SJames Wright @brief Retrieve the user context for a `MATCEED`. 102258600ac3SJames Wright 102358600ac3SJames Wright Collective across MPI processes. 102458600ac3SJames Wright 102558600ac3SJames Wright @param[in,out] mat `MATCEED` 102658600ac3SJames Wright @param[in] ctx User context 102758600ac3SJames Wright 102858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 102958600ac3SJames Wright **/ 103058600ac3SJames Wright PetscErrorCode MatCeedGetContext(Mat mat, void *ctx) { 103158600ac3SJames Wright PetscContainer user_ctx; 103258600ac3SJames Wright 103358600ac3SJames Wright PetscFunctionBeginUser; 103458600ac3SJames Wright PetscCall(PetscObjectQuery((PetscObject)mat, "MatCeed user context", (PetscObject *)&user_ctx)); 103558600ac3SJames Wright if (user_ctx) PetscCall(PetscContainerGetPointer(user_ctx, (void **)ctx)); 103658600ac3SJames Wright else *(void **)ctx = NULL; 103758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 103858600ac3SJames Wright } 103958600ac3SJames Wright /** 104040d80af1SJames Wright @brief Set a user defined matrix operation for a `MATCEED` matrix. 104140d80af1SJames Wright 104240d80af1SJames Wright Within each user-defined routine, the user should call `MatCeedGetContext()` to obtain the user-defined context that was set by 104340d80af1SJames Wright `MatCeedSetContext()`. 104458600ac3SJames Wright 104558600ac3SJames Wright Collective across MPI processes. 104658600ac3SJames Wright 104758600ac3SJames Wright @param[in,out] mat `MATCEED` 104840d80af1SJames Wright @param[in] op Name of the `MatOperation` 104940d80af1SJames Wright @param[in] g Function that provides the operation 105058600ac3SJames Wright 105158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 105258600ac3SJames Wright **/ 1053b846ad1aSJames Wright PetscErrorCode MatCeedSetOperation(Mat mat, MatOperation op, void (*g)(void)) { 105440d80af1SJames Wright PetscFunctionBeginUser; 1055b846ad1aSJames Wright PetscCall(MatShellSetOperation(mat, op, (MatSetOpFn)g)); 1056b846ad1aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1057b846ad1aSJames Wright } 1058b846ad1aSJames Wright 1059b846ad1aSJames Wright /** 1060b846ad1aSJames Wright @brief Set the flag for whether the `MATCEED` should reuse a COO matrix, even if not created by this `MATCEED`. 1061b846ad1aSJames Wright 1062b846ad1aSJames Wright @note Only set this flag if you are certain that the COO layout is properly set on incoming matrices. 1063b846ad1aSJames Wright 1064b846ad1aSJames Wright Collective across MPI processes. 1065b846ad1aSJames Wright 1066b846ad1aSJames Wright @param[in,out] mat `MATCEED` 1067b846ad1aSJames Wright @param[in] coo_reuse_preallocation Flag value to set 1068b846ad1aSJames Wright 1069b846ad1aSJames Wright @return An error code: 0 - success, otherwise - failure 1070b846ad1aSJames Wright **/ 1071b846ad1aSJames Wright PetscErrorCode MatCeedSetReusePreallocationCOO(Mat mat, PetscBool coo_reuse_preallocation) { 1072b846ad1aSJames Wright MatCeedContext ctx; 1073b846ad1aSJames Wright 1074b846ad1aSJames Wright PetscFunctionBeginUser; 1075b846ad1aSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1076b846ad1aSJames Wright ctx->coo_reuse_preallocation = coo_reuse_preallocation; 1077b846ad1aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1078b846ad1aSJames Wright } 1079b846ad1aSJames Wright 1080b846ad1aSJames Wright /** 1081b846ad1aSJames Wright @brief Gets the flag for whether the `MATCEED` should reuse a COO matrix, even if not created by this `MATCEED`. 1082b846ad1aSJames Wright 1083b846ad1aSJames Wright Collective across MPI processes. 1084b846ad1aSJames Wright 1085b846ad1aSJames Wright @param[in] mat `MATCEED` 1086b846ad1aSJames Wright @param[in] coo_reuse_preallocation Address to store current flag value 1087b846ad1aSJames Wright 1088b846ad1aSJames Wright @return An error code: 0 - success, otherwise - failure 1089b846ad1aSJames Wright **/ 1090b846ad1aSJames Wright PetscErrorCode MatCeedGetReusePreallocationCOO(Mat mat, PetscBool *coo_reuse_preallocation) { 1091b846ad1aSJames Wright MatCeedContext ctx; 1092b846ad1aSJames Wright 1093b846ad1aSJames Wright PetscFunctionBeginUser; 1094b846ad1aSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1095b846ad1aSJames Wright *coo_reuse_preallocation = ctx->coo_reuse_preallocation; 109640d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 109740d80af1SJames Wright } 109840d80af1SJames Wright 109940d80af1SJames Wright /** 110040d80af1SJames Wright @brief Sets the default COO matrix type as a string from the `MATCEED`. 110140d80af1SJames Wright 110240d80af1SJames Wright Collective across MPI processes. 110340d80af1SJames Wright 110440d80af1SJames Wright @param[in,out] mat `MATCEED` 110540d80af1SJames Wright @param[in] type COO `MatType` to set 110640d80af1SJames Wright 110740d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 110840d80af1SJames Wright **/ 110940d80af1SJames Wright PetscErrorCode MatCeedSetCOOMatType(Mat mat, MatType type) { 111058600ac3SJames Wright MatCeedContext ctx; 111158600ac3SJames Wright 111258600ac3SJames Wright PetscFunctionBeginUser; 111358600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 111458600ac3SJames Wright // Check if same 111558600ac3SJames Wright { 111658600ac3SJames Wright size_t len_old, len_new; 111758600ac3SJames Wright PetscBool is_same = PETSC_FALSE; 111858600ac3SJames Wright 111940d80af1SJames Wright PetscCall(PetscStrlen(ctx->coo_mat_type, &len_old)); 112058600ac3SJames Wright PetscCall(PetscStrlen(type, &len_new)); 112140d80af1SJames Wright if (len_old == len_new) PetscCall(PetscStrncmp(ctx->coo_mat_type, type, len_old, &is_same)); 112258600ac3SJames Wright if (is_same) PetscFunctionReturn(PETSC_SUCCESS); 112358600ac3SJames Wright } 112458600ac3SJames Wright // Clean up old mats in different format 112558600ac3SJames Wright // LCOV_EXCL_START 112658600ac3SJames Wright if (ctx->mat_assembled_full_internal) { 112758600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 112858600ac3SJames Wright if (ctx->mats_assembled_full[i] == ctx->mat_assembled_full_internal) { 112958600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_full; j++) { 113058600ac3SJames Wright ctx->mats_assembled_full[j - 1] = ctx->mats_assembled_full[j]; 113158600ac3SJames Wright } 113258600ac3SJames Wright ctx->num_mats_assembled_full--; 113358600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 113458600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 113558600ac3SJames Wright } 113658600ac3SJames Wright } 113758600ac3SJames Wright } 113858600ac3SJames Wright if (ctx->mat_assembled_pbd_internal) { 113958600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 114058600ac3SJames Wright if (ctx->mats_assembled_pbd[i] == ctx->mat_assembled_pbd_internal) { 114158600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_pbd; j++) { 114258600ac3SJames Wright ctx->mats_assembled_pbd[j - 1] = ctx->mats_assembled_pbd[j]; 114358600ac3SJames Wright } 114458600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 114558600ac3SJames Wright ctx->num_mats_assembled_pbd--; 114658600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 114758600ac3SJames Wright } 114858600ac3SJames Wright } 114958600ac3SJames Wright } 115040d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 115140d80af1SJames Wright PetscCall(PetscStrallocpy(type, &ctx->coo_mat_type)); 115258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 115358600ac3SJames Wright // LCOV_EXCL_STOP 115458600ac3SJames Wright } 115558600ac3SJames Wright 115658600ac3SJames Wright /** 115740d80af1SJames Wright @brief Gets the default COO matrix type as a string from the `MATCEED`. 115858600ac3SJames Wright 115958600ac3SJames Wright Collective across MPI processes. 116058600ac3SJames Wright 116158600ac3SJames Wright @param[in,out] mat `MATCEED` 116240d80af1SJames Wright @param[in] type COO `MatType` 116358600ac3SJames Wright 116458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 116558600ac3SJames Wright **/ 116640d80af1SJames Wright PetscErrorCode MatCeedGetCOOMatType(Mat mat, MatType *type) { 116758600ac3SJames Wright MatCeedContext ctx; 116858600ac3SJames Wright 116958600ac3SJames Wright PetscFunctionBeginUser; 117058600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 117140d80af1SJames Wright *type = ctx->coo_mat_type; 117258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 117358600ac3SJames Wright } 117458600ac3SJames Wright 117558600ac3SJames Wright /** 117658600ac3SJames Wright @brief Set input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 117758600ac3SJames Wright 117858600ac3SJames Wright Not collective across MPI processes. 117958600ac3SJames Wright 118058600ac3SJames Wright @param[in,out] mat `MATCEED` 118158600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 118258600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 118358600ac3SJames Wright 118458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 118558600ac3SJames Wright **/ 118658600ac3SJames Wright PetscErrorCode MatCeedSetLocalVectors(Mat mat, Vec X_loc, Vec Y_loc_transpose) { 118758600ac3SJames Wright MatCeedContext ctx; 118858600ac3SJames Wright 118958600ac3SJames Wright PetscFunctionBeginUser; 119058600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 119158600ac3SJames Wright if (X_loc) { 119258600ac3SJames Wright PetscInt len_old, len_new; 119358600ac3SJames Wright 119458600ac3SJames Wright PetscCall(VecGetSize(ctx->X_loc, &len_old)); 119558600ac3SJames Wright PetscCall(VecGetSize(X_loc, &len_new)); 119658600ac3SJames 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, 119758600ac3SJames Wright len_new, len_old); 119840d80af1SJames Wright PetscCall(VecReferenceCopy(X_loc, &ctx->X_loc)); 119958600ac3SJames Wright } 120058600ac3SJames Wright if (Y_loc_transpose) { 120158600ac3SJames Wright PetscInt len_old, len_new; 120258600ac3SJames Wright 120358600ac3SJames Wright PetscCall(VecGetSize(ctx->Y_loc_transpose, &len_old)); 120458600ac3SJames Wright PetscCall(VecGetSize(Y_loc_transpose, &len_new)); 120558600ac3SJames Wright PetscCheck(len_old == len_new, PETSC_COMM_SELF, PETSC_ERR_LIB, 120658600ac3SJames Wright "new Y_loc_transpose length %" PetscInt_FMT " should match old Y_loc_transpose length %" PetscInt_FMT, len_new, len_old); 120740d80af1SJames Wright PetscCall(VecReferenceCopy(Y_loc_transpose, &ctx->Y_loc_transpose)); 120858600ac3SJames Wright } 120958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 121058600ac3SJames Wright } 121158600ac3SJames Wright 121258600ac3SJames Wright /** 121358600ac3SJames Wright @brief Get input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 121458600ac3SJames Wright 121558600ac3SJames Wright Not collective across MPI processes. 121658600ac3SJames Wright 121758600ac3SJames Wright @param[in,out] mat `MATCEED` 121858600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 121958600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 122058600ac3SJames Wright 122158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 122258600ac3SJames Wright **/ 122358600ac3SJames Wright PetscErrorCode MatCeedGetLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 122458600ac3SJames Wright MatCeedContext ctx; 122558600ac3SJames Wright 122658600ac3SJames Wright PetscFunctionBeginUser; 122758600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 122858600ac3SJames Wright if (X_loc) { 122940d80af1SJames Wright *X_loc = NULL; 123040d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->X_loc, X_loc)); 123158600ac3SJames Wright } 123258600ac3SJames Wright if (Y_loc_transpose) { 123340d80af1SJames Wright *Y_loc_transpose = NULL; 123440d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->Y_loc_transpose, Y_loc_transpose)); 123558600ac3SJames Wright } 123658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 123758600ac3SJames Wright } 123858600ac3SJames Wright 123958600ac3SJames Wright /** 124058600ac3SJames Wright @brief Restore input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 124158600ac3SJames Wright 124258600ac3SJames Wright Not collective across MPI processes. 124358600ac3SJames Wright 124458600ac3SJames Wright @param[in,out] mat MatCeed 124558600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 124658600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 124758600ac3SJames Wright 124858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 124958600ac3SJames Wright **/ 125058600ac3SJames Wright PetscErrorCode MatCeedRestoreLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 125158600ac3SJames Wright PetscFunctionBeginUser; 125258600ac3SJames Wright if (X_loc) PetscCall(VecDestroy(X_loc)); 125358600ac3SJames Wright if (Y_loc_transpose) PetscCall(VecDestroy(Y_loc_transpose)); 125458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 125558600ac3SJames Wright } 125658600ac3SJames Wright 125758600ac3SJames Wright /** 125858600ac3SJames Wright @brief Get libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 125958600ac3SJames Wright 126058600ac3SJames Wright Not collective across MPI processes. 126158600ac3SJames Wright 126258600ac3SJames Wright @param[in,out] mat MatCeed 126358600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 126458600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 126558600ac3SJames Wright 126658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 126758600ac3SJames Wright **/ 126858600ac3SJames Wright PetscErrorCode MatCeedGetCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 126958600ac3SJames Wright MatCeedContext ctx; 127058600ac3SJames Wright 127158600ac3SJames Wright PetscFunctionBeginUser; 127258600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 127358600ac3SJames Wright if (op_mult) { 127458600ac3SJames Wright *op_mult = NULL; 127550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult, op_mult)); 127658600ac3SJames Wright } 127758600ac3SJames Wright if (op_mult_transpose) { 127858600ac3SJames Wright *op_mult_transpose = NULL; 127950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult_transpose, op_mult_transpose)); 128058600ac3SJames Wright } 128158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 128258600ac3SJames Wright } 128358600ac3SJames Wright 128458600ac3SJames Wright /** 128558600ac3SJames Wright @brief Restore libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 128658600ac3SJames Wright 128758600ac3SJames Wright Not collective across MPI processes. 128858600ac3SJames Wright 128958600ac3SJames Wright @param[in,out] mat MatCeed 129058600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 129158600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 129258600ac3SJames Wright 129358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 129458600ac3SJames Wright **/ 129558600ac3SJames Wright PetscErrorCode MatCeedRestoreCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 129658600ac3SJames Wright MatCeedContext ctx; 129758600ac3SJames Wright 129858600ac3SJames Wright PetscFunctionBeginUser; 129958600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 130050f50432SJames Wright if (op_mult) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult)); 130150f50432SJames Wright if (op_mult_transpose) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult_transpose)); 130258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 130358600ac3SJames Wright } 130458600ac3SJames Wright 130558600ac3SJames Wright /** 130658600ac3SJames Wright @brief Set `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 130758600ac3SJames Wright 130858600ac3SJames Wright Not collective across MPI processes. 130958600ac3SJames Wright 131058600ac3SJames Wright @param[in,out] mat MatCeed 131158600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 131258600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 131358600ac3SJames Wright 131458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 131558600ac3SJames Wright **/ 131658600ac3SJames Wright PetscErrorCode MatCeedSetLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 131758600ac3SJames Wright MatCeedContext ctx; 131858600ac3SJames Wright 131958600ac3SJames Wright PetscFunctionBeginUser; 132058600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 132158600ac3SJames Wright if (log_event_mult) ctx->log_event_mult = log_event_mult; 132258600ac3SJames Wright if (log_event_mult_transpose) ctx->log_event_mult_transpose = log_event_mult_transpose; 132358600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 132458600ac3SJames Wright } 132558600ac3SJames Wright 132658600ac3SJames Wright /** 132758600ac3SJames Wright @brief Get `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 132858600ac3SJames Wright 132958600ac3SJames Wright Not collective across MPI processes. 133058600ac3SJames Wright 133158600ac3SJames Wright @param[in,out] mat MatCeed 133258600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 133358600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 133458600ac3SJames Wright 133558600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 133658600ac3SJames Wright **/ 133758600ac3SJames Wright PetscErrorCode MatCeedGetLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 133858600ac3SJames Wright MatCeedContext ctx; 133958600ac3SJames Wright 134058600ac3SJames Wright PetscFunctionBeginUser; 134158600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 134258600ac3SJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_mult; 134358600ac3SJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_mult_transpose; 134458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 134558600ac3SJames Wright } 134658600ac3SJames Wright 1347c63b910fSJames Wright /** 1348c63b910fSJames Wright @brief Set `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1349c63b910fSJames Wright 1350c63b910fSJames Wright Not collective across MPI processes. 1351c63b910fSJames Wright 1352c63b910fSJames Wright @param[in,out] mat MatCeed 1353c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1354c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1355c63b910fSJames Wright 1356c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1357c63b910fSJames Wright **/ 1358c63b910fSJames Wright PetscErrorCode MatCeedSetCeedOperatorLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 1359c63b910fSJames Wright MatCeedContext ctx; 1360c63b910fSJames Wright 1361c63b910fSJames Wright PetscFunctionBeginUser; 1362c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1363c63b910fSJames Wright if (log_event_mult) ctx->log_event_ceed_mult = log_event_mult; 1364c63b910fSJames Wright if (log_event_mult_transpose) ctx->log_event_ceed_mult_transpose = log_event_mult_transpose; 1365c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1366c63b910fSJames Wright } 1367c63b910fSJames Wright 1368c63b910fSJames Wright /** 1369c63b910fSJames Wright @brief Get `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1370c63b910fSJames Wright 1371c63b910fSJames Wright Not collective across MPI processes. 1372c63b910fSJames Wright 1373c63b910fSJames Wright @param[in,out] mat MatCeed 1374c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1375c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1376c63b910fSJames Wright 1377c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1378c63b910fSJames Wright **/ 1379c63b910fSJames Wright PetscErrorCode MatCeedGetCeedOperatorLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 1380c63b910fSJames Wright MatCeedContext ctx; 1381c63b910fSJames Wright 1382c63b910fSJames Wright PetscFunctionBeginUser; 1383c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1384c63b910fSJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_ceed_mult; 1385c63b910fSJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_ceed_mult_transpose; 1386c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1387c63b910fSJames Wright } 1388c63b910fSJames Wright 138958600ac3SJames Wright // ----------------------------------------------------------------------------- 139058600ac3SJames Wright // Operator context data 139158600ac3SJames Wright // ----------------------------------------------------------------------------- 139258600ac3SJames Wright 139358600ac3SJames Wright /** 139458600ac3SJames Wright @brief Setup context data for operator application. 139558600ac3SJames Wright 139658600ac3SJames Wright Collective across MPI processes. 139758600ac3SJames Wright 139858600ac3SJames Wright @param[in] dm_x Input `DM` 139958600ac3SJames Wright @param[in] dm_y Output `DM` 140058600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 140158600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 140258600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 140358600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 140458600ac3SJames Wright @param[in] log_event_mult `PetscLogEvent` for forward evaluation 140558600ac3SJames Wright @param[in] log_event_mult_transpose `PetscLogEvent` for transpose evaluation 1406c63b910fSJames Wright @param[in] log_event_ceed_mult `PetscLogEvent` for forward `CeedOperator` evaluation 1407c63b910fSJames Wright @param[in] log_event_ceed_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation 140858600ac3SJames Wright @param[out] ctx Context data for operator evaluation 140958600ac3SJames Wright 141058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 141158600ac3SJames Wright **/ 141258600ac3SJames Wright PetscErrorCode MatCeedContextCreate(DM dm_x, DM dm_y, Vec X_loc, Vec Y_loc_transpose, CeedOperator op_mult, CeedOperator op_mult_transpose, 1413c63b910fSJames Wright PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose, PetscLogEvent log_event_ceed_mult, 1414c63b910fSJames Wright PetscLogEvent log_event_ceed_mult_transpose, MatCeedContext *ctx) { 141558600ac3SJames Wright CeedSize x_loc_len, y_loc_len; 141658600ac3SJames Wright 141758600ac3SJames Wright PetscFunctionBeginUser; 141858600ac3SJames Wright // Allocate 141958600ac3SJames Wright PetscCall(PetscNew(ctx)); 142058600ac3SJames Wright (*ctx)->ref_count = 1; 142158600ac3SJames Wright 142258600ac3SJames Wright // Logging 142358600ac3SJames Wright (*ctx)->log_event_mult = log_event_mult; 142458600ac3SJames Wright (*ctx)->log_event_mult_transpose = log_event_mult_transpose; 1425c63b910fSJames Wright (*ctx)->log_event_ceed_mult = log_event_ceed_mult; 1426c63b910fSJames Wright (*ctx)->log_event_ceed_mult_transpose = log_event_ceed_mult_transpose; 142758600ac3SJames Wright 142858600ac3SJames Wright // PETSc objects 142940d80af1SJames Wright PetscCall(DMReferenceCopy(dm_x, &(*ctx)->dm_x)); 143040d80af1SJames Wright PetscCall(DMReferenceCopy(dm_y, &(*ctx)->dm_y)); 143140d80af1SJames Wright if (X_loc) PetscCall(VecReferenceCopy(X_loc, &(*ctx)->X_loc)); 143240d80af1SJames Wright if (Y_loc_transpose) PetscCall(VecReferenceCopy(Y_loc_transpose, &(*ctx)->Y_loc_transpose)); 143358600ac3SJames Wright 143458600ac3SJames Wright // Memtype 143558600ac3SJames Wright { 143658600ac3SJames Wright const PetscScalar *x; 143758600ac3SJames Wright Vec X; 143858600ac3SJames Wright 143958600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &X)); 144058600ac3SJames Wright PetscCall(VecGetArrayReadAndMemType(X, &x, &(*ctx)->mem_type)); 144158600ac3SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X, &x)); 144258600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &X)); 144358600ac3SJames Wright } 144458600ac3SJames Wright 144558600ac3SJames Wright // libCEED objects 144658600ac3SJames Wright PetscCheck(CeedOperatorGetCeed(op_mult, &(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, 144758600ac3SJames Wright "retrieving Ceed context object failed"); 144850f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetActiveVectorLengths(op_mult, &x_loc_len, &y_loc_len)); 144950f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult, &(*ctx)->op_mult)); 145050f50432SJames Wright if (op_mult_transpose) PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult_transpose, &(*ctx)->op_mult_transpose)); 1451b846ad1aSJames Wright if (x_loc_len == -1) x_loc_len = 0; 145250f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, x_loc_len, &(*ctx)->x_loc)); 1453b846ad1aSJames Wright if (y_loc_len == -1) y_loc_len = 0; 145450f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, y_loc_len, &(*ctx)->y_loc)); 145558600ac3SJames Wright 145658600ac3SJames Wright // Flop counting 145758600ac3SJames Wright { 145858600ac3SJames Wright CeedSize ceed_flops_estimate = 0; 145958600ac3SJames Wright 146050f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult, &ceed_flops_estimate)); 146158600ac3SJames Wright (*ctx)->flops_mult = ceed_flops_estimate; 146258600ac3SJames Wright if (op_mult_transpose) { 146350f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult_transpose, &ceed_flops_estimate)); 146458600ac3SJames Wright (*ctx)->flops_mult_transpose = ceed_flops_estimate; 146558600ac3SJames Wright } 146658600ac3SJames Wright } 146758600ac3SJames Wright 146858600ac3SJames Wright // Check sizes 146958600ac3SJames Wright if (x_loc_len > 0 || y_loc_len > 0) { 147058600ac3SJames Wright CeedSize ctx_x_loc_len, ctx_y_loc_len; 147158600ac3SJames Wright PetscInt X_loc_len, dm_x_loc_len, Y_loc_len, dm_y_loc_len; 147258600ac3SJames Wright Vec dm_X_loc, dm_Y_loc; 147358600ac3SJames Wright 147458600ac3SJames Wright // -- Input 147558600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &dm_X_loc)); 147658600ac3SJames Wright PetscCall(VecGetLocalSize(dm_X_loc, &dm_x_loc_len)); 147758600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &dm_X_loc)); 147850f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->x_loc, &ctx_x_loc_len)); 14794c17272bSJames Wright if (X_loc) { 14804c17272bSJames Wright PetscCall(VecGetLocalSize(X_loc, &X_loc_len)); 14814c17272bSJames Wright PetscCheck(X_loc_len == dm_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 14824c17272bSJames Wright "X_loc (%" PetscInt_FMT ") must match dm_x (%" PetscInt_FMT ") dimensions", X_loc_len, dm_x_loc_len); 14834c17272bSJames Wright } 14844c17272bSJames 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", 14854c17272bSJames Wright x_loc_len, dm_x_loc_len); 14864c17272bSJames 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 ")", 14874c17272bSJames Wright x_loc_len, ctx_x_loc_len); 148858600ac3SJames Wright 148958600ac3SJames Wright // -- Output 149058600ac3SJames Wright PetscCall(DMGetLocalVector(dm_y, &dm_Y_loc)); 149158600ac3SJames Wright PetscCall(VecGetLocalSize(dm_Y_loc, &dm_y_loc_len)); 149258600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_y, &dm_Y_loc)); 149350f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->y_loc, &ctx_y_loc_len)); 14944c17272bSJames 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", 14954c17272bSJames Wright ctx_y_loc_len, dm_y_loc_len); 149658600ac3SJames Wright 149758600ac3SJames Wright // -- Transpose 149858600ac3SJames Wright if (Y_loc_transpose) { 149958600ac3SJames Wright PetscCall(VecGetLocalSize(Y_loc_transpose, &Y_loc_len)); 15004c17272bSJames Wright PetscCheck(Y_loc_len == dm_y_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 15014c17272bSJames Wright "Y_loc_transpose (%" PetscInt_FMT ") must match dm_y (%" PetscInt_FMT ") dimensions", Y_loc_len, dm_y_loc_len); 150258600ac3SJames Wright } 150358600ac3SJames Wright } 150458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 150558600ac3SJames Wright } 150658600ac3SJames Wright 150758600ac3SJames Wright /** 150858600ac3SJames Wright @brief Increment reference counter for `MATCEED` context. 150958600ac3SJames Wright 151058600ac3SJames Wright Not collective across MPI processes. 151158600ac3SJames Wright 151258600ac3SJames Wright @param[in,out] ctx Context data 151358600ac3SJames Wright 151458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 151558600ac3SJames Wright **/ 151658600ac3SJames Wright PetscErrorCode MatCeedContextReference(MatCeedContext ctx) { 151758600ac3SJames Wright PetscFunctionBeginUser; 151858600ac3SJames Wright ctx->ref_count++; 151958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 152058600ac3SJames Wright } 152158600ac3SJames Wright 152258600ac3SJames Wright /** 152358600ac3SJames Wright @brief Copy reference for `MATCEED`. 152458600ac3SJames Wright Note: If `ctx_copy` is non-null, it is assumed to be a valid pointer to a `MatCeedContext`. 152558600ac3SJames Wright 152658600ac3SJames Wright Not collective across MPI processes. 152758600ac3SJames Wright 152858600ac3SJames Wright @param[in] ctx Context data 152958600ac3SJames Wright @param[out] ctx_copy Copy of pointer to context data 153058600ac3SJames Wright 153158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 153258600ac3SJames Wright **/ 153358600ac3SJames Wright PetscErrorCode MatCeedContextReferenceCopy(MatCeedContext ctx, MatCeedContext *ctx_copy) { 153458600ac3SJames Wright PetscFunctionBeginUser; 153558600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 153667aa9f91SJames Wright PetscCall(MatCeedContextDestroy(ctx_copy)); 153758600ac3SJames Wright *ctx_copy = ctx; 153858600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 153958600ac3SJames Wright } 154058600ac3SJames Wright 154158600ac3SJames Wright /** 154258600ac3SJames Wright @brief Destroy context data for operator application. 154358600ac3SJames Wright 154458600ac3SJames Wright Collective across MPI processes. 154558600ac3SJames Wright 154658600ac3SJames Wright @param[in,out] ctx Context data for operator evaluation 154758600ac3SJames Wright 154858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 154958600ac3SJames Wright **/ 155067aa9f91SJames Wright PetscErrorCode MatCeedContextDestroy(MatCeedContext *ctx) { 155158600ac3SJames Wright PetscFunctionBeginUser; 155267aa9f91SJames Wright if (!ctx || --(*ctx)->ref_count > 0) PetscFunctionReturn(PETSC_SUCCESS); 155358600ac3SJames Wright 155458600ac3SJames Wright // PETSc objects 155567aa9f91SJames Wright PetscCall(DMDestroy(&(*ctx)->dm_x)); 155667aa9f91SJames Wright PetscCall(DMDestroy(&(*ctx)->dm_y)); 155767aa9f91SJames Wright PetscCall(VecDestroy(&(*ctx)->X_loc)); 155867aa9f91SJames Wright PetscCall(VecDestroy(&(*ctx)->Y_loc_transpose)); 155967aa9f91SJames Wright PetscCall(MatDestroy(&(*ctx)->mat_assembled_full_internal)); 156067aa9f91SJames Wright PetscCall(MatDestroy(&(*ctx)->mat_assembled_pbd_internal)); 156167aa9f91SJames Wright PetscCall(PetscFree((*ctx)->coo_mat_type)); 156267aa9f91SJames Wright PetscCall(PetscFree((*ctx)->mats_assembled_full)); 156367aa9f91SJames Wright PetscCall(PetscFree((*ctx)->mats_assembled_pbd)); 156458600ac3SJames Wright 156558600ac3SJames Wright // libCEED objects 156667aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->x_loc)); 156767aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->y_loc)); 156867aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->coo_values_full)); 156967aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorDestroy(&(*ctx)->coo_values_pbd)); 157067aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorDestroy(&(*ctx)->op_mult)); 157167aa9f91SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorDestroy(&(*ctx)->op_mult_transpose)); 157267aa9f91SJames Wright PetscCheck(CeedDestroy(&(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, "destroying libCEED context object failed"); 157358600ac3SJames Wright 157458600ac3SJames Wright // Deallocate 157567aa9f91SJames Wright (*ctx)->is_destroyed = PETSC_TRUE; // Flag as destroyed in case someone has stale ref 157667aa9f91SJames Wright PetscCall(PetscFree(*ctx)); 157758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 157858600ac3SJames Wright } 157958600ac3SJames Wright 158058600ac3SJames Wright /** 158158600ac3SJames Wright @brief Compute the diagonal of an operator via libCEED. 158258600ac3SJames Wright 158358600ac3SJames Wright Collective across MPI processes. 158458600ac3SJames Wright 158558600ac3SJames Wright @param[in] A `MATCEED` 158658600ac3SJames Wright @param[out] D Vector holding operator diagonal 158758600ac3SJames Wright 158858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 158958600ac3SJames Wright **/ 159058600ac3SJames Wright PetscErrorCode MatGetDiagonal_Ceed(Mat A, Vec D) { 159158600ac3SJames Wright PetscMemType mem_type; 159258600ac3SJames Wright Vec D_loc; 159358600ac3SJames Wright MatCeedContext ctx; 159458600ac3SJames Wright 159558600ac3SJames Wright PetscFunctionBeginUser; 159658600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 159758600ac3SJames Wright 159858600ac3SJames Wright // Place PETSc vector in libCEED vector 1599c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 160058600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &D_loc)); 1601a7dac1d5SJames Wright PetscCall(VecPetscToCeed(D_loc, &mem_type, ctx->x_loc)); 160258600ac3SJames Wright 160358600ac3SJames Wright // Compute Diagonal 1604c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 160550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleDiagonal(ctx->op_mult, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1606c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 160758600ac3SJames Wright 160858600ac3SJames Wright // Restore PETSc vector 1609a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, mem_type, D_loc)); 161058600ac3SJames Wright 161158600ac3SJames Wright // Local-to-Global 161258600ac3SJames Wright PetscCall(VecZeroEntries(D)); 161358600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, D_loc, ADD_VALUES, D)); 161458600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &D_loc)); 1615c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 161658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 161758600ac3SJames Wright } 161858600ac3SJames Wright 161958600ac3SJames Wright /** 162058600ac3SJames Wright @brief Compute `A X = Y` for a `MATCEED`. 162158600ac3SJames Wright 162258600ac3SJames Wright Collective across MPI processes. 162358600ac3SJames Wright 162458600ac3SJames Wright @param[in] A `MATCEED` 162558600ac3SJames Wright @param[in] X Input PETSc vector 162658600ac3SJames Wright @param[out] Y Output PETSc vector 162758600ac3SJames Wright 162858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 162958600ac3SJames Wright **/ 163058600ac3SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 163158600ac3SJames Wright MatCeedContext ctx; 163258600ac3SJames Wright 163358600ac3SJames Wright PetscFunctionBeginUser; 163458600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1635c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult, A, X, Y, NULL)); 163658600ac3SJames Wright 163758600ac3SJames Wright { 163858600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 163958600ac3SJames Wright Vec X_loc = ctx->X_loc, Y_loc; 164058600ac3SJames Wright 164158600ac3SJames Wright // Get local vectors 164258600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 164358600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 164458600ac3SJames Wright 164558600ac3SJames Wright // Global-to-local 164658600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc)); 164758600ac3SJames Wright 164858600ac3SJames Wright // Setup libCEED vectors 1649a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 165058600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc)); 1651a7dac1d5SJames Wright PetscCall(VecPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 165258600ac3SJames Wright 165358600ac3SJames Wright // Apply libCEED operator 1654c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult, A, X, Y, NULL)); 1655537ec908SJames Wright PetscCall(PetscLogGpuTimeBegin()); 165650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult, ctx->x_loc, ctx->y_loc, CEED_REQUEST_IMMEDIATE)); 1657ed5c6999SJames Wright // Log flops 1658ed5c6999SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult)); 1659ed5c6999SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult)); 166058600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1661537ec908SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult, A, X, Y, NULL)); 166258600ac3SJames Wright 166358600ac3SJames Wright // Restore PETSc vectors 1664a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1665a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 166658600ac3SJames Wright 166758600ac3SJames Wright // Local-to-global 166858600ac3SJames Wright PetscCall(VecZeroEntries(Y)); 166958600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y)); 167058600ac3SJames Wright 167158600ac3SJames Wright // Restore local vectors, as needed 167258600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 167358600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 167458600ac3SJames Wright } 167558600ac3SJames Wright 1676c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult, A, X, Y, NULL)); 167758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 167858600ac3SJames Wright } 167958600ac3SJames Wright 168058600ac3SJames Wright /** 168158600ac3SJames Wright @brief Compute `A^T Y = X` for a `MATCEED`. 168258600ac3SJames Wright 168358600ac3SJames Wright Collective across MPI processes. 168458600ac3SJames Wright 168558600ac3SJames Wright @param[in] A `MATCEED` 168658600ac3SJames Wright @param[in] Y Input PETSc vector 168758600ac3SJames Wright @param[out] X Output PETSc vector 168858600ac3SJames Wright 168958600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 169058600ac3SJames Wright **/ 169158600ac3SJames Wright PetscErrorCode MatMultTranspose_Ceed(Mat A, Vec Y, Vec X) { 169258600ac3SJames Wright MatCeedContext ctx; 169358600ac3SJames Wright 169458600ac3SJames Wright PetscFunctionBeginUser; 169558600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1696c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult_transpose, A, Y, X, NULL)); 169758600ac3SJames Wright 169858600ac3SJames Wright { 169958600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 170058600ac3SJames Wright Vec X_loc, Y_loc = ctx->Y_loc_transpose; 170158600ac3SJames Wright 170258600ac3SJames Wright // Get local vectors 170358600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 170458600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 170558600ac3SJames Wright 170658600ac3SJames Wright // Global-to-local 170758600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_y, Y, INSERT_VALUES, Y_loc)); 170858600ac3SJames Wright 170958600ac3SJames Wright // Setup libCEED vectors 1710a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 171158600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 1712a7dac1d5SJames Wright PetscCall(VecPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 171358600ac3SJames Wright 171458600ac3SJames Wright // Apply libCEED operator 1715c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 1716537ec908SJames Wright PetscCall(PetscLogGpuTimeBegin()); 171750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult_transpose, ctx->y_loc, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1718ed5c6999SJames Wright // Log flops 1719ed5c6999SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult_transpose)); 1720ed5c6999SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult_transpose)); 172158600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1722537ec908SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 172358600ac3SJames Wright 172458600ac3SJames Wright // Restore PETSc vectors 1725a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1726a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 172758600ac3SJames Wright 172858600ac3SJames Wright // Local-to-global 172958600ac3SJames Wright PetscCall(VecZeroEntries(X)); 173058600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, X_loc, ADD_VALUES, X)); 173158600ac3SJames Wright 173258600ac3SJames Wright // Restore local vectors, as needed 173358600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 173458600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 173558600ac3SJames Wright } 173658600ac3SJames Wright 1737c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult_transpose, A, Y, X, NULL)); 173858600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 173958600ac3SJames Wright } 1740