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 1958600ac3SJames Wright PetscClassId MATCEED_CLASSID; 20c63b910fSJames Wright PetscLogEvent MATCEED_MULT, MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE, MATCEED_MULT_TRANSPOSE_CEEDOP, MATCEED_ASSEMBLE_DIAGONAL, 21c63b910fSJames Wright MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, MATCEED_SETUP_PBDIAGONAL, MATCEED_SETUP_PBDIAGONAL_CEEDOP, MATCEED_ASSEMBLE_PBDIAGONAL, 22c63b910fSJames Wright MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, MATCEED_SETUP_FULL, MATCEED_SETUP_FULL_CEEDOP, MATCEED_ASSEMBLE_FULL, MATCEED_ASSEMBLE_FULL_CEEDOP; 2358600ac3SJames Wright 2458600ac3SJames Wright /** 2558600ac3SJames Wright @brief Register MATCEED log events. 2658600ac3SJames Wright 2758600ac3SJames Wright Not collective across MPI processes. 2858600ac3SJames Wright 2958600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 3058600ac3SJames Wright **/ 3158600ac3SJames Wright static PetscErrorCode MatCeedRegisterLogEvents() { 3240d80af1SJames Wright static PetscBool registered = PETSC_FALSE; 3358600ac3SJames Wright 3458600ac3SJames Wright PetscFunctionBeginUser; 3558600ac3SJames Wright if (registered) PetscFunctionReturn(PETSC_SUCCESS); 36c63b910fSJames Wright PetscCall(PetscClassIdRegister("MatCEED", &MATCEED_CLASSID)); 37c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMul", MATCEED_CLASSID, &MATCEED_MULT)); 38c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulCeed", MATCEED_CLASSID, &MATCEED_MULT_CEEDOP)); 39c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulT", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE)); 40c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDMulTCeed", MATCEED_CLASSID, &MATCEED_MULT_TRANSPOSE_CEEDOP)); 41c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmDiag", MATCEED_CLASSID, &MATCEED_ASSEMBLE_DIAGONAL)); 42c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSU", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL)); 43c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_PBDIAGONAL_CEEDOP)); 44c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBD", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL)); 45c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmPBDCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP)); 46c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSU", MATCEED_CLASSID, &MATCEED_SETUP_FULL)); 47c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmSUCeed", MATCEED_CLASSID, &MATCEED_SETUP_FULL_CEEDOP)); 48c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsm", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL)); 49c63b910fSJames Wright PetscCall(PetscLogEventRegister("MatCEEDAsmCeed", MATCEED_CLASSID, &MATCEED_ASSEMBLE_FULL_CEEDOP)); 5040d80af1SJames Wright registered = PETSC_TRUE; 5158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 5258600ac3SJames Wright } 5358600ac3SJames Wright 5458600ac3SJames Wright /** 5558600ac3SJames Wright @brief Assemble the point block diagonal of a `MATCEED` into a `MATAIJ` or similar. 5658600ac3SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 5758600ac3SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 5858600ac3SJames Wright 5958600ac3SJames Wright Collective across MPI processes. 6058600ac3SJames Wright 6158600ac3SJames Wright @param[in] mat_ceed `MATCEED` to assemble 6258600ac3SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 6358600ac3SJames Wright 6458600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 6558600ac3SJames Wright **/ 6658600ac3SJames Wright static PetscErrorCode MatCeedAssemblePointBlockDiagonalCOO(Mat mat_ceed, Mat mat_coo) { 6758600ac3SJames Wright MatCeedContext ctx; 6858600ac3SJames Wright 6958600ac3SJames Wright PetscFunctionBeginUser; 7058600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 7158600ac3SJames Wright 7258600ac3SJames Wright // Check if COO pattern set 7358600ac3SJames Wright { 7458600ac3SJames Wright PetscInt index = -1; 7558600ac3SJames Wright 7658600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 7758600ac3SJames Wright if (ctx->mats_assembled_pbd[i] == mat_coo) index = i; 7858600ac3SJames Wright } 7958600ac3SJames Wright if (index == -1) { 8058600ac3SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 8158600ac3SJames Wright CeedInt *rows_ceed, *cols_ceed; 8258600ac3SJames Wright PetscCount num_entries; 8358600ac3SJames Wright PetscLogStage stage_amg_setup; 8458600ac3SJames Wright 8558600ac3SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 86c63b910fSJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 8758600ac3SJames Wright if (stage_amg_setup == -1) { 88c63b910fSJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 8958600ac3SJames Wright } 9058600ac3SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 91c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 92c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 9350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonalSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 94c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 95a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 96a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 9758600ac3SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 9858600ac3SJames Wright free(rows_petsc); 9958600ac3SJames Wright free(cols_petsc); 10050f50432SJames Wright if (!ctx->coo_values_pbd) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_pbd)); 10158600ac3SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_pbd * sizeof(Mat), &ctx->mats_assembled_pbd)); 10258600ac3SJames Wright ctx->mats_assembled_pbd[ctx->num_mats_assembled_pbd - 1] = mat_coo; 103c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 10458600ac3SJames Wright PetscCall(PetscLogStagePop()); 10558600ac3SJames Wright } 10658600ac3SJames Wright } 10758600ac3SJames Wright 10858600ac3SJames Wright // Assemble mat_ceed 109c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 11058600ac3SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 11158600ac3SJames Wright { 11258600ac3SJames Wright const CeedScalar *values; 11358600ac3SJames Wright MatType mat_type; 11458600ac3SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 11558600ac3SJames Wright PetscBool is_spd, is_spd_known; 11658600ac3SJames Wright 11758600ac3SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 11858600ac3SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 11958600ac3SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 12058600ac3SJames Wright else mem_type = CEED_MEM_HOST; 12158600ac3SJames Wright 122c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 12350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemblePointBlockDiagonal(ctx->op_mult, ctx->coo_values_pbd, CEED_REQUEST_IMMEDIATE)); 124c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 12550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_pbd, mem_type, &values)); 12658600ac3SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 12758600ac3SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 12858600ac3SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 12950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_pbd, &values)); 13058600ac3SJames Wright } 13158600ac3SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 132c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_PBDIAGONAL, mat_ceed, mat_coo, NULL, NULL)); 13358600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 13458600ac3SJames Wright } 13558600ac3SJames Wright 13658600ac3SJames Wright /** 13758600ac3SJames Wright @brief Assemble inner `Mat` for diagonal `PC` operations 13858600ac3SJames Wright 13958600ac3SJames Wright Collective across MPI processes. 14058600ac3SJames Wright 14158600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 14258600ac3SJames Wright @param[in] use_ceed_pbd Boolean flag to use libCEED PBD assembly 14358600ac3SJames Wright @param[out] mat_inner Inner `Mat` for diagonal operations 14458600ac3SJames Wright 14558600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 14658600ac3SJames Wright **/ 14758600ac3SJames Wright static PetscErrorCode MatCeedAssembleInnerBlockDiagonalMat(Mat mat_ceed, PetscBool use_ceed_pbd, Mat *mat_inner) { 14858600ac3SJames Wright MatCeedContext ctx; 14958600ac3SJames Wright 15058600ac3SJames Wright PetscFunctionBeginUser; 15158600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 15258600ac3SJames Wright if (use_ceed_pbd) { 15358600ac3SJames Wright // Check if COO pattern set 15440d80af1SJames Wright if (!ctx->mat_assembled_pbd_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_pbd_internal)); 15558600ac3SJames Wright 15658600ac3SJames Wright // Assemble mat_assembled_full_internal 15758600ac3SJames Wright PetscCall(MatCeedAssemblePointBlockDiagonalCOO(mat_ceed, ctx->mat_assembled_pbd_internal)); 15858600ac3SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_pbd_internal; 15958600ac3SJames Wright } else { 16058600ac3SJames Wright // Check if COO pattern set 16140d80af1SJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 16258600ac3SJames Wright 16358600ac3SJames Wright // Assemble mat_assembled_full_internal 16458600ac3SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 16558600ac3SJames Wright if (mat_inner) *mat_inner = ctx->mat_assembled_full_internal; 16658600ac3SJames Wright } 16758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 16858600ac3SJames Wright } 16958600ac3SJames Wright 17058600ac3SJames Wright /** 171c1bdbf00SJames Wright @brief Get on-process diagonal block of `MATCEED` 172c1bdbf00SJames Wright 173c1bdbf00SJames Wright This is a block per-process of the diagonal of the global matrix. 174c1bdbf00SJames Wright This is NOT the diagonal blocks associated with the block size of the matrix (i.e. `MatSetBlockSize()` has no effect on this function). 17558600ac3SJames Wright 17658600ac3SJames Wright Collective across MPI processes. 17758600ac3SJames Wright 17858600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 17958600ac3SJames Wright @param[out] mat_block The diagonal block matrix 18058600ac3SJames Wright 18158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 18258600ac3SJames Wright **/ 18358600ac3SJames Wright static PetscErrorCode MatGetDiagonalBlock_Ceed(Mat mat_ceed, Mat *mat_block) { 18458600ac3SJames Wright MatCeedContext ctx; 18558600ac3SJames Wright 18658600ac3SJames Wright PetscFunctionBeginUser; 18758600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 18858600ac3SJames Wright 189c1bdbf00SJames Wright // Check if COO pattern set 190c1bdbf00SJames Wright if (!ctx->mat_assembled_full_internal) PetscCall(MatCeedCreateMatCOO(mat_ceed, &ctx->mat_assembled_full_internal)); 19158600ac3SJames Wright 192c1bdbf00SJames Wright // Assemble mat_assembled_full_internal 193c1bdbf00SJames Wright PetscCall(MatCeedAssembleCOO(mat_ceed, ctx->mat_assembled_full_internal)); 194c1bdbf00SJames Wright 195c1bdbf00SJames Wright // Get diagonal block 196c1bdbf00SJames Wright PetscCall(MatGetDiagonalBlock(ctx->mat_assembled_full_internal, mat_block)); 19758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 19858600ac3SJames Wright } 19958600ac3SJames Wright 20058600ac3SJames Wright /** 20158600ac3SJames Wright @brief Invert `MATCEED` diagonal block for Jacobi. 20258600ac3SJames Wright 20358600ac3SJames Wright Collective across MPI processes. 20458600ac3SJames Wright 20558600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 20658600ac3SJames Wright @param[out] values The block inverses in column major order 20758600ac3SJames Wright 20858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 20958600ac3SJames Wright **/ 21058600ac3SJames Wright static PetscErrorCode MatInvertBlockDiagonal_Ceed(Mat mat_ceed, const PetscScalar **values) { 21158600ac3SJames Wright Mat mat_inner = NULL; 21258600ac3SJames Wright MatCeedContext ctx; 21358600ac3SJames Wright 21458600ac3SJames Wright PetscFunctionBeginUser; 21558600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 21658600ac3SJames Wright 21758600ac3SJames Wright // Assemble inner mat if needed 21858600ac3SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_pbd_valid, &mat_inner)); 21958600ac3SJames Wright 22058600ac3SJames Wright // Invert PB diagonal 22158600ac3SJames Wright PetscCall(MatInvertBlockDiagonal(mat_inner, values)); 22258600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 22358600ac3SJames Wright } 22458600ac3SJames Wright 22558600ac3SJames Wright /** 22658600ac3SJames Wright @brief Invert `MATCEED` variable diagonal block for Jacobi. 22758600ac3SJames Wright 22858600ac3SJames Wright Collective across MPI processes. 22958600ac3SJames Wright 23058600ac3SJames Wright @param[in] mat_ceed `MATCEED` to invert 23158600ac3SJames Wright @param[in] num_blocks The number of blocks on the process 23258600ac3SJames Wright @param[in] block_sizes The size of each block on the process 23358600ac3SJames Wright @param[out] values The block inverses in column major order 23458600ac3SJames Wright 23558600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 23658600ac3SJames Wright **/ 23758600ac3SJames Wright static PetscErrorCode MatInvertVariableBlockDiagonal_Ceed(Mat mat_ceed, PetscInt num_blocks, const PetscInt *block_sizes, PetscScalar *values) { 23858600ac3SJames Wright Mat mat_inner = NULL; 23958600ac3SJames Wright MatCeedContext ctx; 24058600ac3SJames Wright 24158600ac3SJames Wright PetscFunctionBeginUser; 24258600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 24358600ac3SJames Wright 24458600ac3SJames Wright // Assemble inner mat if needed 24558600ac3SJames Wright PetscCall(MatCeedAssembleInnerBlockDiagonalMat(mat_ceed, ctx->is_ceed_vpbd_valid, &mat_inner)); 24658600ac3SJames Wright 24758600ac3SJames Wright // Invert PB diagonal 24858600ac3SJames Wright PetscCall(MatInvertVariableBlockDiagonal(mat_inner, num_blocks, block_sizes, values)); 24958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 25058600ac3SJames Wright } 25158600ac3SJames Wright 252e90c2ceeSJames Wright /** 253e90c2ceeSJames Wright @brief View `MATCEED`. 254e90c2ceeSJames Wright 255e90c2ceeSJames Wright Collective across MPI processes. 256e90c2ceeSJames Wright 257e90c2ceeSJames Wright @param[in] mat_ceed `MATCEED` to view 258e90c2ceeSJames Wright @param[in] viewer The visualization context 259e90c2ceeSJames Wright 260e90c2ceeSJames Wright @return An error code: 0 - success, otherwise - failure 261e90c2ceeSJames Wright **/ 262e90c2ceeSJames Wright static PetscErrorCode MatView_Ceed(Mat mat_ceed, PetscViewer viewer) { 263e90c2ceeSJames Wright PetscBool is_ascii; 264e90c2ceeSJames Wright PetscViewerFormat format; 265000d2032SJeremy L Thompson PetscMPIInt size, rank; 266e90c2ceeSJames Wright MatCeedContext ctx; 267e90c2ceeSJames Wright 268e90c2ceeSJames Wright PetscFunctionBeginUser; 269e90c2ceeSJames Wright PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 270e90c2ceeSJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 271e90c2ceeSJames Wright if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat_ceed), &viewer)); 272e90c2ceeSJames Wright 273e90c2ceeSJames Wright PetscCall(PetscViewerGetFormat(viewer, &format)); 274e90c2ceeSJames Wright PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat_ceed), &size)); 275e90c2ceeSJames Wright if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 276e90c2ceeSJames Wright 277000d2032SJeremy L Thompson PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat_ceed), &rank)); 278000d2032SJeremy L Thompson if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS); 279000d2032SJeremy L Thompson 280e90c2ceeSJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii)); 281e90c2ceeSJames Wright { 282000d2032SJeremy L Thompson PetscBool is_detailed = format == PETSC_VIEWER_ASCII_INFO_DETAIL; 283000d2032SJeremy L Thompson char rank_string[16] = {'\0'}; 284e90c2ceeSJames Wright FILE *file; 285e90c2ceeSJames Wright 286*dfdd2b92SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "MatCEED:\n")); 287537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // MatCEED 288*dfdd2b92SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "Default COO MatType: %s\n", ctx->coo_mat_type)); 289000d2032SJeremy L Thompson PetscCall(PetscSNPrintf(rank_string, 16, "on Rank %d", rank)); 290000d2032SJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator Apply %s:\n", is_detailed ? rank_string : "Summary")); 291537ec908SJames Wright PetscCall(PetscViewerASCIIGetPointer(viewer, &file)); 292537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 293000d2032SJeremy L Thompson if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult, file)); 294000d2032SJeremy L Thompson else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult, file)); 295537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 296e90c2ceeSJames Wright if (ctx->op_mult_transpose) { 297000d2032SJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(viewer, "CeedOperator ApplyTranspose %s:\n", is_detailed ? rank_string : "Summary")); 298537ec908SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // CeedOperator 299000d2032SJeremy L Thompson if (is_detailed) PetscCallCeed(ctx->ceed, CeedOperatorView(ctx->op_mult_transpose, file)); 300000d2032SJeremy L Thompson else PetscCallCeed(ctx->ceed, CeedOperatorViewTerse(ctx->op_mult_transpose, file)); 301537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // CeedOperator 302e90c2ceeSJames Wright } 303537ec908SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // MatCEED 304e90c2ceeSJames Wright } 305e90c2ceeSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 306e90c2ceeSJames Wright } 307e90c2ceeSJames Wright 30858600ac3SJames Wright // ----------------------------------------------------------------------------- 30958600ac3SJames Wright // MatCeed 31058600ac3SJames Wright // ----------------------------------------------------------------------------- 31158600ac3SJames Wright 31258600ac3SJames Wright /** 31358600ac3SJames Wright @brief Create PETSc `Mat` from libCEED operators. 31458600ac3SJames Wright 31558600ac3SJames Wright Collective across MPI processes. 31658600ac3SJames Wright 31758600ac3SJames Wright @param[in] dm_x Input `DM` 31858600ac3SJames Wright @param[in] dm_y Output `DM` 31958600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 32058600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 32158600ac3SJames Wright @param[out] mat New MatCeed 32258600ac3SJames Wright 32358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 32458600ac3SJames Wright **/ 325000d2032SJeremy L Thompson PetscErrorCode MatCreateCeed(DM dm_x, DM dm_y, CeedOperator op_mult, CeedOperator op_mult_transpose, Mat *mat) { 32658600ac3SJames Wright PetscInt X_l_size, X_g_size, Y_l_size, Y_g_size; 32758600ac3SJames Wright VecType vec_type; 32858600ac3SJames Wright MatCeedContext ctx; 32958600ac3SJames Wright 33058600ac3SJames Wright PetscFunctionBeginUser; 33158600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 33258600ac3SJames Wright 33358600ac3SJames Wright // Collect context data 33458600ac3SJames Wright PetscCall(DMGetVecType(dm_x, &vec_type)); 33558600ac3SJames Wright { 33658600ac3SJames Wright Vec X; 33758600ac3SJames Wright 33858600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_x, &X)); 33958600ac3SJames Wright PetscCall(VecGetSize(X, &X_g_size)); 34058600ac3SJames Wright PetscCall(VecGetLocalSize(X, &X_l_size)); 34158600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_x, &X)); 34258600ac3SJames Wright } 34358600ac3SJames Wright if (dm_y) { 34458600ac3SJames Wright Vec Y; 34558600ac3SJames Wright 34658600ac3SJames Wright PetscCall(DMGetGlobalVector(dm_y, &Y)); 34758600ac3SJames Wright PetscCall(VecGetSize(Y, &Y_g_size)); 34858600ac3SJames Wright PetscCall(VecGetLocalSize(Y, &Y_l_size)); 34958600ac3SJames Wright PetscCall(DMRestoreGlobalVector(dm_y, &Y)); 35058600ac3SJames Wright } else { 35158600ac3SJames Wright dm_y = dm_x; 35258600ac3SJames Wright Y_g_size = X_g_size; 35358600ac3SJames Wright Y_l_size = X_l_size; 35458600ac3SJames Wright } 35540d80af1SJames Wright 35658600ac3SJames Wright // Create context 35758600ac3SJames Wright { 35858600ac3SJames Wright Vec X_loc, Y_loc_transpose = NULL; 35958600ac3SJames Wright 36058600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_x, &X_loc)); 36158600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 36258600ac3SJames Wright if (op_mult_transpose) { 36358600ac3SJames Wright PetscCall(DMCreateLocalVector(dm_y, &Y_loc_transpose)); 36458600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc_transpose)); 36558600ac3SJames Wright } 366c63b910fSJames Wright PetscCall(MatCeedContextCreate(dm_x, dm_y, X_loc, Y_loc_transpose, op_mult, op_mult_transpose, MATCEED_MULT, MATCEED_MULT_TRANSPOSE, 367c63b910fSJames Wright MATCEED_MULT_CEEDOP, MATCEED_MULT_TRANSPOSE_CEEDOP, &ctx)); 36858600ac3SJames Wright PetscCall(VecDestroy(&X_loc)); 36958600ac3SJames Wright PetscCall(VecDestroy(&Y_loc_transpose)); 37058600ac3SJames Wright } 37158600ac3SJames Wright 37258600ac3SJames Wright // Create mat 37358600ac3SJames Wright PetscCall(MatCreateShell(PetscObjectComm((PetscObject)dm_x), Y_l_size, X_l_size, Y_g_size, X_g_size, ctx, mat)); 37458600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)*mat, MATCEED)); 37558600ac3SJames Wright // -- Set block and variable block sizes 37658600ac3SJames Wright if (dm_x == dm_y) { 37758600ac3SJames Wright MatType dm_mat_type, dm_mat_type_copy; 37858600ac3SJames Wright Mat temp_mat; 37958600ac3SJames Wright 38058600ac3SJames Wright PetscCall(DMGetMatType(dm_x, &dm_mat_type)); 38158600ac3SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 38258600ac3SJames Wright PetscCall(DMSetMatType(dm_x, MATAIJ)); 38358600ac3SJames Wright PetscCall(DMCreateMatrix(dm_x, &temp_mat)); 38458600ac3SJames Wright PetscCall(DMSetMatType(dm_x, dm_mat_type_copy)); 38558600ac3SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 38658600ac3SJames Wright 38758600ac3SJames Wright { 38858600ac3SJames Wright PetscInt block_size, num_blocks, max_vblock_size = PETSC_INT_MAX; 38958600ac3SJames Wright const PetscInt *vblock_sizes; 39058600ac3SJames Wright 39158600ac3SJames Wright // -- Get block sizes 39258600ac3SJames Wright PetscCall(MatGetBlockSize(temp_mat, &block_size)); 39358600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(temp_mat, &num_blocks, &vblock_sizes)); 39458600ac3SJames Wright { 39558600ac3SJames Wright PetscInt local_min_max[2] = {0}, global_min_max[2] = {0, PETSC_INT_MAX}; 39658600ac3SJames Wright 39758600ac3SJames Wright for (PetscInt i = 0; i < num_blocks; i++) local_min_max[1] = PetscMax(local_min_max[1], vblock_sizes[i]); 39858600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_min_max, global_min_max)); 39958600ac3SJames Wright max_vblock_size = global_min_max[1]; 40058600ac3SJames Wright } 40158600ac3SJames Wright 40258600ac3SJames Wright // -- Copy block sizes 40358600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(*mat, block_size)); 40458600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(*mat, num_blocks, (PetscInt *)vblock_sizes)); 40558600ac3SJames Wright 40658600ac3SJames Wright // -- Check libCEED compatibility 40758600ac3SJames Wright { 40858600ac3SJames Wright bool is_composite; 40958600ac3SJames Wright 41058600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_TRUE; 41158600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_TRUE; 41250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorIsComposite(op_mult, &is_composite)); 41358600ac3SJames Wright if (is_composite) { 41458600ac3SJames Wright CeedInt num_sub_operators; 41558600ac3SJames Wright CeedOperator *sub_operators; 41658600ac3SJames Wright 41750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetNumSub(op_mult, &num_sub_operators)); 41850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedCompositeOperatorGetSubList(op_mult, &sub_operators)); 41958600ac3SJames Wright for (CeedInt i = 0; i < num_sub_operators; i++) { 42058600ac3SJames Wright CeedInt num_bases, num_comp; 42158600ac3SJames Wright CeedBasis *active_bases; 42258600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 42358600ac3SJames Wright 42450f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(sub_operators[i], &assembly_data)); 42550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 42650f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 42758600ac3SJames Wright if (num_bases > 1) { 42858600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 42958600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 43058600ac3SJames Wright } 43158600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 43258600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 43358600ac3SJames Wright } 43458600ac3SJames Wright } else { 43558600ac3SJames Wright // LCOV_EXCL_START 43658600ac3SJames Wright CeedInt num_bases, num_comp; 43758600ac3SJames Wright CeedBasis *active_bases; 43858600ac3SJames Wright CeedOperatorAssemblyData assembly_data; 43958600ac3SJames Wright 44050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetOperatorAssemblyData(op_mult, &assembly_data)); 44150f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorAssemblyDataGetBases(assembly_data, &num_bases, &active_bases, NULL, NULL, NULL, NULL)); 44250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedBasisGetNumComponents(active_bases[0], &num_comp)); 44358600ac3SJames Wright if (num_bases > 1) { 44458600ac3SJames Wright ctx->is_ceed_pbd_valid = PETSC_FALSE; 44558600ac3SJames Wright ctx->is_ceed_vpbd_valid = PETSC_FALSE; 44658600ac3SJames Wright } 44758600ac3SJames Wright if (num_comp != block_size) ctx->is_ceed_pbd_valid = PETSC_FALSE; 44858600ac3SJames Wright if (num_comp < max_vblock_size) ctx->is_ceed_vpbd_valid = PETSC_FALSE; 44958600ac3SJames Wright // LCOV_EXCL_STOP 45058600ac3SJames Wright } 45158600ac3SJames Wright { 45258600ac3SJames Wright PetscInt local_is_valid[2], global_is_valid[2]; 45358600ac3SJames Wright 45458600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_pbd_valid; 45558600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 45658600ac3SJames Wright ctx->is_ceed_pbd_valid = global_is_valid[0]; 45758600ac3SJames Wright local_is_valid[0] = local_is_valid[1] = ctx->is_ceed_vpbd_valid; 45858600ac3SJames Wright PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm_x), local_is_valid, global_is_valid)); 45958600ac3SJames Wright ctx->is_ceed_vpbd_valid = global_is_valid[0]; 46058600ac3SJames Wright } 46158600ac3SJames Wright } 46258600ac3SJames Wright } 46358600ac3SJames Wright PetscCall(MatDestroy(&temp_mat)); 46458600ac3SJames Wright } 46558600ac3SJames Wright // -- Set internal mat type 46658600ac3SJames Wright { 46758600ac3SJames Wright VecType vec_type; 46840d80af1SJames Wright MatType coo_mat_type; 46958600ac3SJames Wright 47058600ac3SJames Wright PetscCall(VecGetType(ctx->X_loc, &vec_type)); 47140d80af1SJames Wright if (strstr(vec_type, VECCUDA)) coo_mat_type = MATAIJCUSPARSE; 47240d80af1SJames Wright else if (strstr(vec_type, VECKOKKOS)) coo_mat_type = MATAIJKOKKOS; 47340d80af1SJames Wright else coo_mat_type = MATAIJ; 47440d80af1SJames Wright PetscCall(PetscStrallocpy(coo_mat_type, &ctx->coo_mat_type)); 47558600ac3SJames Wright } 47658600ac3SJames Wright // -- Set mat operations 47758600ac3SJames Wright PetscCall(MatShellSetContextDestroy(*mat, (PetscErrorCode(*)(void *))MatCeedContextDestroy)); 478e90c2ceeSJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 47958600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 48058600ac3SJames Wright if (op_mult_transpose) PetscCall(MatShellSetOperation(*mat, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 48158600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 48258600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 48358600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_INVERT_BLOCK_DIAGONAL, (void (*)(void))MatInvertBlockDiagonal_Ceed)); 48458600ac3SJames Wright PetscCall(MatShellSetOperation(*mat, MATOP_INVERT_VBLOCK_DIAGONAL, (void (*)(void))MatInvertVariableBlockDiagonal_Ceed)); 48558600ac3SJames Wright PetscCall(MatShellSetVecType(*mat, vec_type)); 48658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 48758600ac3SJames Wright } 48858600ac3SJames Wright 48958600ac3SJames Wright /** 49058600ac3SJames Wright @brief Copy `MATCEED` into a compatible `Mat` with type `MatShell` or `MATCEED`. 49158600ac3SJames Wright 49258600ac3SJames Wright Collective across MPI processes. 49358600ac3SJames Wright 49458600ac3SJames Wright @param[in] mat_ceed `MATCEED` to copy from 49558600ac3SJames Wright @param[out] mat_other `MatShell` or `MATCEED` to copy into 49658600ac3SJames Wright 49758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 49858600ac3SJames Wright **/ 49958600ac3SJames Wright PetscErrorCode MatCeedCopy(Mat mat_ceed, Mat mat_other) { 50058600ac3SJames Wright PetscFunctionBeginUser; 50158600ac3SJames Wright PetscCall(MatCeedRegisterLogEvents()); 50258600ac3SJames Wright 50358600ac3SJames Wright // Check type compatibility 50458600ac3SJames Wright { 50540d80af1SJames Wright PetscBool is_matceed = PETSC_FALSE, is_matshell = PETSC_FALSE; 50658600ac3SJames Wright MatType mat_type_ceed, mat_type_other; 50758600ac3SJames Wright 50858600ac3SJames Wright PetscCall(MatGetType(mat_ceed, &mat_type_ceed)); 50940d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_ceed, MATCEED, &is_matceed)); 51040d80af1SJames Wright PetscCheck(is_matceed, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_ceed must have type " MATCEED); 51140d80af1SJames Wright PetscCall(MatGetType(mat_other, &mat_type_other)); 51240d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_other, MATCEED, &is_matceed)); 51340d80af1SJames Wright PetscCall(PetscStrcmp(mat_type_other, MATSHELL, &is_matceed)); 51440d80af1SJames Wright PetscCheck(is_matceed || is_matshell, PETSC_COMM_SELF, PETSC_ERR_LIB, "mat_other must have type " MATCEED " or " MATSHELL); 51558600ac3SJames Wright } 51658600ac3SJames Wright 51758600ac3SJames Wright // Check dimension compatibility 51858600ac3SJames Wright { 51958600ac3SJames 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; 52058600ac3SJames Wright 52158600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_ceed_size, &X_g_ceed_size)); 52258600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_ceed_size, &X_l_ceed_size)); 52358600ac3SJames Wright PetscCall(MatGetSize(mat_ceed, &Y_g_other_size, &X_g_other_size)); 52458600ac3SJames Wright PetscCall(MatGetLocalSize(mat_ceed, &Y_l_other_size, &X_l_other_size)); 52558600ac3SJames 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) && 52658600ac3SJames Wright (X_l_ceed_size == X_l_other_size), 52758600ac3SJames Wright PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, 52858600ac3SJames Wright "mat_ceed and mat_other must have compatible sizes; found mat_ceed (Global: %" PetscInt_FMT ", %" PetscInt_FMT 52958600ac3SJames Wright "; Local: %" PetscInt_FMT ", %" PetscInt_FMT ") mat_other (Global: %" PetscInt_FMT ", %" PetscInt_FMT "; Local: %" PetscInt_FMT 53058600ac3SJames Wright ", %" PetscInt_FMT ")", 53158600ac3SJames 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); 53258600ac3SJames Wright } 53358600ac3SJames Wright 53458600ac3SJames Wright // Convert 53558600ac3SJames Wright { 53658600ac3SJames Wright VecType vec_type; 53758600ac3SJames Wright MatCeedContext ctx; 53858600ac3SJames Wright 53958600ac3SJames Wright PetscCall(PetscObjectChangeTypeName((PetscObject)mat_other, MATCEED)); 54058600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 54158600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 54258600ac3SJames Wright PetscCall(MatShellSetContext(mat_other, ctx)); 54358600ac3SJames Wright PetscCall(MatShellSetContextDestroy(mat_other, (PetscErrorCode(*)(void *))MatCeedContextDestroy)); 544e90c2ceeSJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_VIEW, (void (*)(void))MatView_Ceed)); 54558600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 54658600ac3SJames Wright if (ctx->op_mult_transpose) PetscCall(MatShellSetOperation(mat_other, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Ceed)); 54758600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Ceed)); 54858600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_GET_DIAGONAL_BLOCK, (void (*)(void))MatGetDiagonalBlock_Ceed)); 54958600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_INVERT_BLOCK_DIAGONAL, (void (*)(void))MatInvertBlockDiagonal_Ceed)); 55058600ac3SJames Wright PetscCall(MatShellSetOperation(mat_other, MATOP_INVERT_VBLOCK_DIAGONAL, (void (*)(void))MatInvertVariableBlockDiagonal_Ceed)); 55158600ac3SJames Wright { 55258600ac3SJames Wright PetscInt block_size; 55358600ac3SJames Wright 55458600ac3SJames Wright PetscCall(MatGetBlockSize(mat_ceed, &block_size)); 55558600ac3SJames Wright if (block_size > 1) PetscCall(MatSetBlockSize(mat_other, block_size)); 55658600ac3SJames Wright } 55758600ac3SJames Wright { 55858600ac3SJames Wright PetscInt num_blocks; 55958600ac3SJames Wright const PetscInt *block_sizes; 56058600ac3SJames Wright 56158600ac3SJames Wright PetscCall(MatGetVariableBlockSizes(mat_ceed, &num_blocks, &block_sizes)); 56258600ac3SJames Wright if (num_blocks) PetscCall(MatSetVariableBlockSizes(mat_other, num_blocks, (PetscInt *)block_sizes)); 56358600ac3SJames Wright } 56458600ac3SJames Wright PetscCall(DMGetVecType(ctx->dm_x, &vec_type)); 56558600ac3SJames Wright PetscCall(MatShellSetVecType(mat_other, vec_type)); 56658600ac3SJames Wright } 56758600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 56858600ac3SJames Wright } 56958600ac3SJames Wright 57058600ac3SJames Wright /** 571ba95ebb4SJeremy L Thompson @brief Mark `CeedQFunction` data as updated and the `CeedQFunction` as requiring re-assembly for a `MatCEED`. 572000d2032SJeremy L Thompson 573000d2032SJeremy L Thompson Collective across MPI processes. 574000d2032SJeremy L Thompson 575000d2032SJeremy L Thompson @param[in] mat_ceed `MATCEED` 576000d2032SJeremy L Thompson @param[out] update_needed Boolean flag indicating `CeedQFunction` update needed 577000d2032SJeremy L Thompson 578000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 579000d2032SJeremy L Thompson **/ 580000d2032SJeremy L Thompson PetscErrorCode MatCeedSetAssemblyDataUpdateNeeded(Mat mat_ceed, PetscBool update_needed) { 581000d2032SJeremy L Thompson MatCeedContext ctx; 582000d2032SJeremy L Thompson 583000d2032SJeremy L Thompson PetscFunctionBeginUser; 584000d2032SJeremy L Thompson PetscCall(MatShellGetContext(mat_ceed, &ctx)); 585000d2032SJeremy L Thompson PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult, update_needed)); 586000d2032SJeremy L Thompson if (ctx->op_mult_transpose) { 587000d2032SJeremy L Thompson PetscCallCeed(ctx->ceed, CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(ctx->op_mult_transpose, update_needed)); 588000d2032SJeremy L Thompson } 589397c0187SJeremy L Thompson if (update_needed) { 590397c0187SJeremy L Thompson PetscCall(MatAssemblyBegin(mat_ceed, MAT_FINAL_ASSEMBLY)); 591397c0187SJeremy L Thompson PetscCall(MatAssemblyEnd(mat_ceed, MAT_FINAL_ASSEMBLY)); 592397c0187SJeremy L Thompson } 593000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 594000d2032SJeremy L Thompson } 595000d2032SJeremy L Thompson 596000d2032SJeremy L Thompson /** 59740d80af1SJames Wright @brief Setup a `Mat` with the same COO pattern as a `MatCEED`. 59840d80af1SJames Wright 59940d80af1SJames Wright Collective across MPI processes. 60040d80af1SJames Wright 60140d80af1SJames Wright @param[in] mat_ceed `MATCEED` 60240d80af1SJames Wright @param[out] mat_coo Sparse `Mat` with same COO pattern 60340d80af1SJames Wright 60440d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 60540d80af1SJames Wright **/ 60640d80af1SJames Wright PetscErrorCode MatCeedCreateMatCOO(Mat mat_ceed, Mat *mat_coo) { 60740d80af1SJames Wright MatCeedContext ctx; 60840d80af1SJames Wright 60940d80af1SJames Wright PetscFunctionBeginUser; 61040d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 61140d80af1SJames Wright 61240d80af1SJames 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"); 61340d80af1SJames Wright 61440d80af1SJames Wright // Check cl mat type 61540d80af1SJames Wright { 61640d80af1SJames Wright PetscBool is_coo_mat_type_cl = PETSC_FALSE; 61740d80af1SJames Wright char coo_mat_type_cl[64]; 61840d80af1SJames Wright 61940d80af1SJames Wright // Check for specific CL coo mat type for this Mat 62040d80af1SJames Wright { 62140d80af1SJames Wright const char *mat_ceed_prefix = NULL; 62240d80af1SJames Wright 62340d80af1SJames Wright PetscCall(MatGetOptionsPrefix(mat_ceed, &mat_ceed_prefix)); 62440d80af1SJames Wright PetscOptionsBegin(PetscObjectComm((PetscObject)mat_ceed), mat_ceed_prefix, "", NULL); 62540d80af1SJames Wright PetscCall(PetscOptionsFList("-ceed_coo_mat_type", "Default MATCEED COO assembly MatType", NULL, MatList, coo_mat_type_cl, coo_mat_type_cl, 62640d80af1SJames Wright sizeof(coo_mat_type_cl), &is_coo_mat_type_cl)); 62740d80af1SJames Wright PetscOptionsEnd(); 62840d80af1SJames Wright if (is_coo_mat_type_cl) { 62940d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 63040d80af1SJames Wright PetscCall(PetscStrallocpy(coo_mat_type_cl, &ctx->coo_mat_type)); 63140d80af1SJames Wright } 63240d80af1SJames Wright } 63340d80af1SJames Wright } 63440d80af1SJames Wright 63540d80af1SJames Wright // Create sparse matrix 63640d80af1SJames Wright { 63740d80af1SJames Wright MatType dm_mat_type, dm_mat_type_copy; 63840d80af1SJames Wright 63940d80af1SJames Wright PetscCall(DMGetMatType(ctx->dm_x, &dm_mat_type)); 64040d80af1SJames Wright PetscCall(PetscStrallocpy(dm_mat_type, (char **)&dm_mat_type_copy)); 64140d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, ctx->coo_mat_type)); 64240d80af1SJames Wright PetscCall(DMCreateMatrix(ctx->dm_x, mat_coo)); 64340d80af1SJames Wright PetscCall(DMSetMatType(ctx->dm_x, dm_mat_type_copy)); 64440d80af1SJames Wright PetscCall(PetscFree(dm_mat_type_copy)); 64540d80af1SJames Wright } 64640d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 64740d80af1SJames Wright } 64840d80af1SJames Wright 64940d80af1SJames Wright /** 65040d80af1SJames Wright @brief Setup the COO preallocation `MATCEED` into a `MATAIJ` or similar. 65158600ac3SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 65258600ac3SJames Wright 65358600ac3SJames Wright Collective across MPI processes. 65458600ac3SJames Wright 65558600ac3SJames Wright @param[in] mat_ceed `MATCEED` to assemble 65658600ac3SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 65758600ac3SJames Wright 65858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 65958600ac3SJames Wright **/ 66040d80af1SJames Wright PetscErrorCode MatCeedSetPreallocationCOO(Mat mat_ceed, Mat mat_coo) { 66158600ac3SJames Wright MatCeedContext ctx; 66258600ac3SJames Wright 66358600ac3SJames Wright PetscFunctionBeginUser; 66458600ac3SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 66558600ac3SJames Wright 66658600ac3SJames Wright { 66758600ac3SJames Wright PetscInt *rows_petsc = NULL, *cols_petsc = NULL; 66858600ac3SJames Wright CeedInt *rows_ceed, *cols_ceed; 66958600ac3SJames Wright PetscCount num_entries; 67058600ac3SJames Wright PetscLogStage stage_amg_setup; 67158600ac3SJames Wright 67258600ac3SJames Wright // -- Assemble sparsity pattern if mat hasn't been assembled before 673c63b910fSJames Wright PetscCall(PetscLogStageGetId("MatCEED Asm Setup", &stage_amg_setup)); 67458600ac3SJames Wright if (stage_amg_setup == -1) { 675c63b910fSJames Wright PetscCall(PetscLogStageRegister("MatCEED Asm Setup", &stage_amg_setup)); 67658600ac3SJames Wright } 67758600ac3SJames Wright PetscCall(PetscLogStagePush(stage_amg_setup)); 678c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 679c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 68050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleSymbolic(ctx->op_mult, &num_entries, &rows_ceed, &cols_ceed)); 681c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 682a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &rows_ceed, &rows_petsc)); 683a7dac1d5SJames Wright PetscCall(IntArrayCeedToPetsc(num_entries, &cols_ceed, &cols_petsc)); 68458600ac3SJames Wright PetscCall(MatSetPreallocationCOOLocal(mat_coo, num_entries, rows_petsc, cols_petsc)); 68558600ac3SJames Wright free(rows_petsc); 68658600ac3SJames Wright free(cols_petsc); 68750f50432SJames Wright if (!ctx->coo_values_full) PetscCallCeed(ctx->ceed, CeedVectorCreate(ctx->ceed, num_entries, &ctx->coo_values_full)); 68858600ac3SJames Wright PetscCall(PetscRealloc(++ctx->num_mats_assembled_full * sizeof(Mat), &ctx->mats_assembled_full)); 68958600ac3SJames Wright ctx->mats_assembled_full[ctx->num_mats_assembled_full - 1] = mat_coo; 690c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_SETUP_FULL, mat_ceed, mat_coo, NULL, NULL)); 69158600ac3SJames Wright PetscCall(PetscLogStagePop()); 69258600ac3SJames Wright } 69340d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 69440d80af1SJames Wright } 69540d80af1SJames Wright 69640d80af1SJames Wright /** 69740d80af1SJames Wright @brief Assemble a `MATCEED` into a `MATAIJ` or similar. 69840d80af1SJames Wright The `mat_coo` preallocation is set to match the sparsity pattern of `mat_ceed`. 69940d80af1SJames Wright The caller is responsible for assuring the global and local sizes are compatible, otherwise this function will fail. 70040d80af1SJames Wright 70140d80af1SJames Wright Collective across MPI processes. 70240d80af1SJames Wright 70340d80af1SJames Wright @param[in] mat_ceed `MATCEED` to assemble 70440d80af1SJames Wright @param[in,out] mat_coo `MATAIJ` or similar to assemble into 70540d80af1SJames Wright 70640d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 70740d80af1SJames Wright **/ 70840d80af1SJames Wright PetscErrorCode MatCeedAssembleCOO(Mat mat_ceed, Mat mat_coo) { 70940d80af1SJames Wright MatCeedContext ctx; 71040d80af1SJames Wright 71140d80af1SJames Wright PetscFunctionBeginUser; 71240d80af1SJames Wright PetscCall(MatShellGetContext(mat_ceed, &ctx)); 71340d80af1SJames Wright 71440d80af1SJames Wright // Set COO pattern if needed 71540d80af1SJames Wright { 71640d80af1SJames Wright CeedInt index = -1; 71740d80af1SJames Wright 71840d80af1SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 71940d80af1SJames Wright if (ctx->mats_assembled_full[i] == mat_coo) index = i; 72040d80af1SJames Wright } 72140d80af1SJames Wright if (index == -1) PetscCall(MatCeedSetPreallocationCOO(mat_ceed, mat_coo)); 72258600ac3SJames Wright } 72358600ac3SJames Wright 72458600ac3SJames Wright // Assemble mat_ceed 725c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 72658600ac3SJames Wright PetscCall(MatAssemblyBegin(mat_coo, MAT_FINAL_ASSEMBLY)); 72758600ac3SJames Wright { 72858600ac3SJames Wright const CeedScalar *values; 72958600ac3SJames Wright MatType mat_type; 73058600ac3SJames Wright CeedMemType mem_type = CEED_MEM_HOST; 73158600ac3SJames Wright PetscBool is_spd, is_spd_known; 73258600ac3SJames Wright 73358600ac3SJames Wright PetscCall(MatGetType(mat_coo, &mat_type)); 73458600ac3SJames Wright if (strstr(mat_type, "cusparse")) mem_type = CEED_MEM_DEVICE; 73558600ac3SJames Wright else if (strstr(mat_type, "kokkos")) mem_type = CEED_MEM_DEVICE; 73658600ac3SJames Wright else mem_type = CEED_MEM_HOST; 73758600ac3SJames Wright 738c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 73950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssemble(ctx->op_mult, ctx->coo_values_full)); 740c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL_CEEDOP, mat_ceed, mat_coo, NULL, NULL)); 74150f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorGetArrayRead(ctx->coo_values_full, mem_type, &values)); 74258600ac3SJames Wright PetscCall(MatSetValuesCOO(mat_coo, values, INSERT_VALUES)); 74358600ac3SJames Wright PetscCall(MatIsSPDKnown(mat_ceed, &is_spd_known, &is_spd)); 74458600ac3SJames Wright if (is_spd_known) PetscCall(MatSetOption(mat_coo, MAT_SPD, is_spd)); 74550f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorRestoreArrayRead(ctx->coo_values_full, &values)); 74658600ac3SJames Wright } 74758600ac3SJames Wright PetscCall(MatAssemblyEnd(mat_coo, MAT_FINAL_ASSEMBLY)); 748c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_FULL, mat_ceed, mat_coo, NULL, NULL)); 74958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 75058600ac3SJames Wright } 75158600ac3SJames Wright 75258600ac3SJames Wright /** 75340d80af1SJames Wright @brief Set the current value of a context field for a `MatCEED`. 75440d80af1SJames Wright 75540d80af1SJames Wright Not collective across MPI processes. 75640d80af1SJames Wright 75740d80af1SJames Wright @param[in,out] mat `MatCEED` 75840d80af1SJames Wright @param[in] name Name of the context field 75940d80af1SJames Wright @param[in] value New context field value 76040d80af1SJames Wright 76140d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 76240d80af1SJames Wright **/ 76340d80af1SJames Wright PetscErrorCode MatCeedSetContextDouble(Mat mat, const char *name, double value) { 76440d80af1SJames Wright PetscBool was_updated = PETSC_FALSE; 76540d80af1SJames Wright MatCeedContext ctx; 76640d80af1SJames Wright 76740d80af1SJames Wright PetscFunctionBeginUser; 76840d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 76940d80af1SJames Wright { 77040d80af1SJames Wright CeedContextFieldLabel label = NULL; 77140d80af1SJames Wright 77240d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult, name, &label)); 77340d80af1SJames Wright if (label) { 774000d2032SJeremy L Thompson double set_value = 2 * value + 1.0; 775000d2032SJeremy L Thompson 776000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 777000d2032SJeremy L Thompson if (set_value != value) { 77840d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult, label, &value)); 77940d80af1SJames Wright was_updated = PETSC_TRUE; 78040d80af1SJames Wright } 781000d2032SJeremy L Thompson } 78240d80af1SJames Wright if (ctx->op_mult_transpose) { 78340d80af1SJames Wright label = NULL; 78440d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(ctx->op_mult_transpose, name, &label)); 78540d80af1SJames Wright if (label) { 786000d2032SJeremy L Thompson double set_value = 2 * value + 1.0; 787000d2032SJeremy L Thompson 788000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, name, &set_value)); 789000d2032SJeremy L Thompson if (set_value != value) { 79040d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorSetContextDouble(ctx->op_mult_transpose, label, &value)); 79140d80af1SJames Wright was_updated = PETSC_TRUE; 79240d80af1SJames Wright } 79340d80af1SJames Wright } 79440d80af1SJames Wright } 795000d2032SJeremy L Thompson } 79640d80af1SJames Wright if (was_updated) { 79740d80af1SJames Wright PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 79840d80af1SJames Wright PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 79940d80af1SJames Wright } 80040d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 80140d80af1SJames Wright } 80240d80af1SJames Wright 80340d80af1SJames Wright /** 80440d80af1SJames Wright @brief Get the current value of a context field for a `MatCEED`. 80540d80af1SJames Wright 80640d80af1SJames Wright Not collective across MPI processes. 80740d80af1SJames Wright 80840d80af1SJames Wright @param[in] mat `MatCEED` 80940d80af1SJames Wright @param[in] name Name of the context field 81040d80af1SJames Wright @param[out] value Current context field value 81140d80af1SJames Wright 81240d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 81340d80af1SJames Wright **/ 81440d80af1SJames Wright PetscErrorCode MatCeedGetContextDouble(Mat mat, const char *name, double *value) { 81540d80af1SJames Wright MatCeedContext ctx; 81640d80af1SJames Wright 81740d80af1SJames Wright PetscFunctionBeginUser; 81840d80af1SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 81940d80af1SJames Wright { 82040d80af1SJames Wright CeedContextFieldLabel label = NULL; 82140d80af1SJames Wright CeedOperator op = ctx->op_mult; 82240d80af1SJames Wright 82340d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 82440d80af1SJames Wright if (!label && ctx->op_mult_transpose) { 82540d80af1SJames Wright op = ctx->op_mult_transpose; 82640d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextFieldLabel(op, name, &label)); 82740d80af1SJames Wright } 82840d80af1SJames Wright if (label) { 82940d80af1SJames Wright PetscSizeT num_values; 83040d80af1SJames Wright const double *values_ceed; 83140d80af1SJames Wright 83240d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorGetContextDoubleRead(op, label, &num_values, &values_ceed)); 83340d80af1SJames Wright *value = values_ceed[0]; 83440d80af1SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorRestoreContextDoubleRead(op, label, &values_ceed)); 83540d80af1SJames Wright } 83640d80af1SJames Wright } 83740d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 83840d80af1SJames Wright } 83940d80af1SJames Wright 84040d80af1SJames Wright /** 841000d2032SJeremy L Thompson @brief Set the current `PetscReal` value of a context field for a `MatCEED`. 842000d2032SJeremy L Thompson 843000d2032SJeremy L Thompson Not collective across MPI processes. 844000d2032SJeremy L Thompson 845000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 846000d2032SJeremy L Thompson @param[in] name Name of the context field 847000d2032SJeremy L Thompson @param[in] value New context field value 848000d2032SJeremy L Thompson 849000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 850000d2032SJeremy L Thompson **/ 851000d2032SJeremy L Thompson PetscErrorCode MatCeedSetContextReal(Mat mat, const char *name, PetscReal value) { 852000d2032SJeremy L Thompson double value_double = value; 853000d2032SJeremy L Thompson 854000d2032SJeremy L Thompson PetscFunctionBeginUser; 855000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, name, value_double)); 856000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 857000d2032SJeremy L Thompson } 858000d2032SJeremy L Thompson 859000d2032SJeremy L Thompson /** 86051bb547fSJames Wright @brief Get the current `PetscReal` value of a context field for a `MatCEED`. 86151bb547fSJames Wright 86251bb547fSJames Wright Not collective across MPI processes. 86351bb547fSJames Wright 86451bb547fSJames Wright @param[in] mat `MatCEED` 86551bb547fSJames Wright @param[in] name Name of the context field 86651bb547fSJames Wright @param[out] value Current context field value 86751bb547fSJames Wright 86851bb547fSJames Wright @return An error code: 0 - success, otherwise - failure 86951bb547fSJames Wright **/ 87051bb547fSJames Wright PetscErrorCode MatCeedGetContextReal(Mat mat, const char *name, PetscReal *value) { 87187d3884fSJeremy L Thompson double value_double = 0.0; 87251bb547fSJames Wright 87351bb547fSJames Wright PetscFunctionBeginUser; 87451bb547fSJames Wright PetscCall(MatCeedGetContextDouble(mat, name, &value_double)); 87551bb547fSJames Wright *value = value_double; 87651bb547fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 87751bb547fSJames Wright } 87851bb547fSJames Wright 87951bb547fSJames Wright /** 880000d2032SJeremy L Thompson @brief Set the current time for a `MatCEED`. 881000d2032SJeremy L Thompson 882000d2032SJeremy L Thompson Not collective across MPI processes. 883000d2032SJeremy L Thompson 884000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 885000d2032SJeremy L Thompson @param[in] time Current time 886000d2032SJeremy L Thompson 887000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 888000d2032SJeremy L Thompson **/ 889000d2032SJeremy L Thompson PetscErrorCode MatCeedSetTime(Mat mat, PetscReal time) { 890000d2032SJeremy L Thompson PetscFunctionBeginUser; 891000d2032SJeremy L Thompson { 892000d2032SJeremy L Thompson double time_ceed = time; 893000d2032SJeremy L Thompson 894000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "time", time_ceed)); 895000d2032SJeremy L Thompson } 896000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 897000d2032SJeremy L Thompson } 898000d2032SJeremy L Thompson 899000d2032SJeremy L Thompson /** 900000d2032SJeremy L Thompson @brief Get the current time for a `MatCEED`. 901000d2032SJeremy L Thompson 902000d2032SJeremy L Thompson Not collective across MPI processes. 903000d2032SJeremy L Thompson 904000d2032SJeremy L Thompson @param[in] mat `MatCEED` 905000d2032SJeremy L Thompson @param[out] time Current time, or -1.0 if the boundary evaluator has no time field 906000d2032SJeremy L Thompson 907000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 908000d2032SJeremy L Thompson **/ 909000d2032SJeremy L Thompson PetscErrorCode MatCeedGetTime(Mat mat, PetscReal *time) { 910000d2032SJeremy L Thompson PetscFunctionBeginUser; 911000d2032SJeremy L Thompson *time = -1.0; 912000d2032SJeremy L Thompson { 913000d2032SJeremy L Thompson double time_ceed = -1.0; 914000d2032SJeremy L Thompson 915000d2032SJeremy L Thompson PetscCall(MatCeedGetContextDouble(mat, "time", &time_ceed)); 916000d2032SJeremy L Thompson *time = time_ceed; 917000d2032SJeremy L Thompson } 918000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 919000d2032SJeremy L Thompson } 920000d2032SJeremy L Thompson 921000d2032SJeremy L Thompson /** 922000d2032SJeremy L Thompson @brief Set the current time step for a `MatCEED`. 923000d2032SJeremy L Thompson 924000d2032SJeremy L Thompson Not collective across MPI processes. 925000d2032SJeremy L Thompson 926000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 927000d2032SJeremy L Thompson @param[in] dt Current time step 928000d2032SJeremy L Thompson 929000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 930000d2032SJeremy L Thompson **/ 931000d2032SJeremy L Thompson PetscErrorCode MatCeedSetDt(Mat mat, PetscReal dt) { 932000d2032SJeremy L Thompson PetscFunctionBeginUser; 933000d2032SJeremy L Thompson { 934000d2032SJeremy L Thompson double dt_ceed = dt; 935000d2032SJeremy L Thompson 936000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "dt", dt_ceed)); 937000d2032SJeremy L Thompson } 938000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 939000d2032SJeremy L Thompson } 940000d2032SJeremy L Thompson 941000d2032SJeremy L Thompson /** 942000d2032SJeremy L Thompson @brief Set the Jacobian shifts for a `MatCEED`. 943000d2032SJeremy L Thompson 944000d2032SJeremy L Thompson Not collective across MPI processes. 945000d2032SJeremy L Thompson 946000d2032SJeremy L Thompson @param[in,out] mat `MatCEED` 947000d2032SJeremy L Thompson @param[in] shift_v Velocity shift 948000d2032SJeremy L Thompson @param[in] shift_a Acceleration shift 949000d2032SJeremy L Thompson 950000d2032SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 951000d2032SJeremy L Thompson **/ 952000d2032SJeremy L Thompson PetscErrorCode MatCeedSetShifts(Mat mat, PetscReal shift_v, PetscReal shift_a) { 953000d2032SJeremy L Thompson PetscFunctionBeginUser; 954000d2032SJeremy L Thompson { 955000d2032SJeremy L Thompson double shift_v_ceed = shift_v; 956000d2032SJeremy L Thompson 957000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "shift v", shift_v_ceed)); 958000d2032SJeremy L Thompson } 959000d2032SJeremy L Thompson if (shift_a) { 960000d2032SJeremy L Thompson double shift_a_ceed = shift_a; 961000d2032SJeremy L Thompson 962000d2032SJeremy L Thompson PetscCall(MatCeedSetContextDouble(mat, "shift a", shift_a_ceed)); 963000d2032SJeremy L Thompson } 964000d2032SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 965000d2032SJeremy L Thompson } 966000d2032SJeremy L Thompson 967000d2032SJeremy L Thompson /** 96858600ac3SJames Wright @brief Set user context for a `MATCEED`. 96958600ac3SJames Wright 97058600ac3SJames Wright Collective across MPI processes. 97158600ac3SJames Wright 97258600ac3SJames Wright @param[in,out] mat `MATCEED` 97358600ac3SJames Wright @param[in] f The context destroy function, or NULL 97458600ac3SJames Wright @param[in] ctx User context, or NULL to unset 97558600ac3SJames Wright 97658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 97758600ac3SJames Wright **/ 97858600ac3SJames Wright PetscErrorCode MatCeedSetContext(Mat mat, PetscErrorCode (*f)(void *), void *ctx) { 97958600ac3SJames Wright PetscContainer user_ctx = NULL; 98058600ac3SJames Wright 98158600ac3SJames Wright PetscFunctionBeginUser; 98258600ac3SJames Wright if (ctx) { 98358600ac3SJames Wright PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)mat), &user_ctx)); 98458600ac3SJames Wright PetscCall(PetscContainerSetPointer(user_ctx, ctx)); 98558600ac3SJames Wright PetscCall(PetscContainerSetUserDestroy(user_ctx, f)); 98658600ac3SJames Wright } 98758600ac3SJames Wright PetscCall(PetscObjectCompose((PetscObject)mat, "MatCeed user context", (PetscObject)user_ctx)); 98858600ac3SJames Wright PetscCall(PetscContainerDestroy(&user_ctx)); 98958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 99058600ac3SJames Wright } 99158600ac3SJames Wright 99258600ac3SJames Wright /** 99358600ac3SJames Wright @brief Retrieve the user context for a `MATCEED`. 99458600ac3SJames Wright 99558600ac3SJames Wright Collective across MPI processes. 99658600ac3SJames Wright 99758600ac3SJames Wright @param[in,out] mat `MATCEED` 99858600ac3SJames Wright @param[in] ctx User context 99958600ac3SJames Wright 100058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 100158600ac3SJames Wright **/ 100258600ac3SJames Wright PetscErrorCode MatCeedGetContext(Mat mat, void *ctx) { 100358600ac3SJames Wright PetscContainer user_ctx; 100458600ac3SJames Wright 100558600ac3SJames Wright PetscFunctionBeginUser; 100658600ac3SJames Wright PetscCall(PetscObjectQuery((PetscObject)mat, "MatCeed user context", (PetscObject *)&user_ctx)); 100758600ac3SJames Wright if (user_ctx) PetscCall(PetscContainerGetPointer(user_ctx, (void **)ctx)); 100858600ac3SJames Wright else *(void **)ctx = NULL; 100958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 101058600ac3SJames Wright } 101158600ac3SJames Wright /** 101240d80af1SJames Wright @brief Set a user defined matrix operation for a `MATCEED` matrix. 101340d80af1SJames Wright 101440d80af1SJames Wright Within each user-defined routine, the user should call `MatCeedGetContext()` to obtain the user-defined context that was set by 101540d80af1SJames Wright `MatCeedSetContext()`. 101658600ac3SJames Wright 101758600ac3SJames Wright Collective across MPI processes. 101858600ac3SJames Wright 101958600ac3SJames Wright @param[in,out] mat `MATCEED` 102040d80af1SJames Wright @param[in] op Name of the `MatOperation` 102140d80af1SJames Wright @param[in] g Function that provides the operation 102258600ac3SJames Wright 102358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 102458600ac3SJames Wright **/ 102540d80af1SJames Wright PetscErrorCode MatCeedSetOperation(Mat mat, MatOperation op, void (*g)(void)) { 102640d80af1SJames Wright PetscFunctionBeginUser; 102740d80af1SJames Wright PetscCall(MatShellSetOperation(mat, op, g)); 102840d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 102940d80af1SJames Wright } 103040d80af1SJames Wright 103140d80af1SJames Wright /** 103240d80af1SJames Wright @brief Sets the default COO matrix type as a string from the `MATCEED`. 103340d80af1SJames Wright 103440d80af1SJames Wright Collective across MPI processes. 103540d80af1SJames Wright 103640d80af1SJames Wright @param[in,out] mat `MATCEED` 103740d80af1SJames Wright @param[in] type COO `MatType` to set 103840d80af1SJames Wright 103940d80af1SJames Wright @return An error code: 0 - success, otherwise - failure 104040d80af1SJames Wright **/ 104140d80af1SJames Wright PetscErrorCode MatCeedSetCOOMatType(Mat mat, MatType type) { 104258600ac3SJames Wright MatCeedContext ctx; 104358600ac3SJames Wright 104458600ac3SJames Wright PetscFunctionBeginUser; 104558600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 104658600ac3SJames Wright // Check if same 104758600ac3SJames Wright { 104858600ac3SJames Wright size_t len_old, len_new; 104958600ac3SJames Wright PetscBool is_same = PETSC_FALSE; 105058600ac3SJames Wright 105140d80af1SJames Wright PetscCall(PetscStrlen(ctx->coo_mat_type, &len_old)); 105258600ac3SJames Wright PetscCall(PetscStrlen(type, &len_new)); 105340d80af1SJames Wright if (len_old == len_new) PetscCall(PetscStrncmp(ctx->coo_mat_type, type, len_old, &is_same)); 105458600ac3SJames Wright if (is_same) PetscFunctionReturn(PETSC_SUCCESS); 105558600ac3SJames Wright } 105658600ac3SJames Wright // Clean up old mats in different format 105758600ac3SJames Wright // LCOV_EXCL_START 105858600ac3SJames Wright if (ctx->mat_assembled_full_internal) { 105958600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_full; i++) { 106058600ac3SJames Wright if (ctx->mats_assembled_full[i] == ctx->mat_assembled_full_internal) { 106158600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_full; j++) { 106258600ac3SJames Wright ctx->mats_assembled_full[j - 1] = ctx->mats_assembled_full[j]; 106358600ac3SJames Wright } 106458600ac3SJames Wright ctx->num_mats_assembled_full--; 106558600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 106658600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 106758600ac3SJames Wright } 106858600ac3SJames Wright } 106958600ac3SJames Wright } 107058600ac3SJames Wright if (ctx->mat_assembled_pbd_internal) { 107158600ac3SJames Wright for (PetscInt i = 0; i < ctx->num_mats_assembled_pbd; i++) { 107258600ac3SJames Wright if (ctx->mats_assembled_pbd[i] == ctx->mat_assembled_pbd_internal) { 107358600ac3SJames Wright for (PetscInt j = i + 1; j < ctx->num_mats_assembled_pbd; j++) { 107458600ac3SJames Wright ctx->mats_assembled_pbd[j - 1] = ctx->mats_assembled_pbd[j]; 107558600ac3SJames Wright } 107658600ac3SJames Wright // Note: we'll realloc this array again, so no need to shrink the allocation 107758600ac3SJames Wright ctx->num_mats_assembled_pbd--; 107858600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 107958600ac3SJames Wright } 108058600ac3SJames Wright } 108158600ac3SJames Wright } 108240d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 108340d80af1SJames Wright PetscCall(PetscStrallocpy(type, &ctx->coo_mat_type)); 108458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 108558600ac3SJames Wright // LCOV_EXCL_STOP 108658600ac3SJames Wright } 108758600ac3SJames Wright 108858600ac3SJames Wright /** 108940d80af1SJames Wright @brief Gets the default COO matrix type as a string from the `MATCEED`. 109058600ac3SJames Wright 109158600ac3SJames Wright Collective across MPI processes. 109258600ac3SJames Wright 109358600ac3SJames Wright @param[in,out] mat `MATCEED` 109440d80af1SJames Wright @param[in] type COO `MatType` 109558600ac3SJames Wright 109658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 109758600ac3SJames Wright **/ 109840d80af1SJames Wright PetscErrorCode MatCeedGetCOOMatType(Mat mat, MatType *type) { 109958600ac3SJames Wright MatCeedContext ctx; 110058600ac3SJames Wright 110158600ac3SJames Wright PetscFunctionBeginUser; 110258600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 110340d80af1SJames Wright *type = ctx->coo_mat_type; 110458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 110558600ac3SJames Wright } 110658600ac3SJames Wright 110758600ac3SJames Wright /** 110858600ac3SJames Wright @brief Set input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 110958600ac3SJames Wright 111058600ac3SJames Wright Not collective across MPI processes. 111158600ac3SJames Wright 111258600ac3SJames Wright @param[in,out] mat `MATCEED` 111358600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 111458600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 111558600ac3SJames Wright 111658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 111758600ac3SJames Wright **/ 111858600ac3SJames Wright PetscErrorCode MatCeedSetLocalVectors(Mat mat, Vec X_loc, Vec Y_loc_transpose) { 111958600ac3SJames Wright MatCeedContext ctx; 112058600ac3SJames Wright 112158600ac3SJames Wright PetscFunctionBeginUser; 112258600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 112358600ac3SJames Wright if (X_loc) { 112458600ac3SJames Wright PetscInt len_old, len_new; 112558600ac3SJames Wright 112658600ac3SJames Wright PetscCall(VecGetSize(ctx->X_loc, &len_old)); 112758600ac3SJames Wright PetscCall(VecGetSize(X_loc, &len_new)); 112858600ac3SJames 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, 112958600ac3SJames Wright len_new, len_old); 113040d80af1SJames Wright PetscCall(VecReferenceCopy(X_loc, &ctx->X_loc)); 113158600ac3SJames Wright } 113258600ac3SJames Wright if (Y_loc_transpose) { 113358600ac3SJames Wright PetscInt len_old, len_new; 113458600ac3SJames Wright 113558600ac3SJames Wright PetscCall(VecGetSize(ctx->Y_loc_transpose, &len_old)); 113658600ac3SJames Wright PetscCall(VecGetSize(Y_loc_transpose, &len_new)); 113758600ac3SJames Wright PetscCheck(len_old == len_new, PETSC_COMM_SELF, PETSC_ERR_LIB, 113858600ac3SJames Wright "new Y_loc_transpose length %" PetscInt_FMT " should match old Y_loc_transpose length %" PetscInt_FMT, len_new, len_old); 113940d80af1SJames Wright PetscCall(VecReferenceCopy(Y_loc_transpose, &ctx->Y_loc_transpose)); 114058600ac3SJames Wright } 114158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 114258600ac3SJames Wright } 114358600ac3SJames Wright 114458600ac3SJames Wright /** 114558600ac3SJames Wright @brief Get input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 114658600ac3SJames Wright 114758600ac3SJames Wright Not collective across MPI processes. 114858600ac3SJames Wright 114958600ac3SJames Wright @param[in,out] mat `MATCEED` 115058600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 115158600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 115258600ac3SJames Wright 115358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 115458600ac3SJames Wright **/ 115558600ac3SJames Wright PetscErrorCode MatCeedGetLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 115658600ac3SJames Wright MatCeedContext ctx; 115758600ac3SJames Wright 115858600ac3SJames Wright PetscFunctionBeginUser; 115958600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 116058600ac3SJames Wright if (X_loc) { 116140d80af1SJames Wright *X_loc = NULL; 116240d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->X_loc, X_loc)); 116358600ac3SJames Wright } 116458600ac3SJames Wright if (Y_loc_transpose) { 116540d80af1SJames Wright *Y_loc_transpose = NULL; 116640d80af1SJames Wright PetscCall(VecReferenceCopy(ctx->Y_loc_transpose, Y_loc_transpose)); 116758600ac3SJames Wright } 116858600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 116958600ac3SJames Wright } 117058600ac3SJames Wright 117158600ac3SJames Wright /** 117258600ac3SJames Wright @brief Restore input local vectors for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 117358600ac3SJames Wright 117458600ac3SJames Wright Not collective across MPI processes. 117558600ac3SJames Wright 117658600ac3SJames Wright @param[in,out] mat MatCeed 117758600ac3SJames Wright @param[out] X_loc Input PETSc local vector, or NULL 117858600ac3SJames Wright @param[out] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 117958600ac3SJames Wright 118058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 118158600ac3SJames Wright **/ 118258600ac3SJames Wright PetscErrorCode MatCeedRestoreLocalVectors(Mat mat, Vec *X_loc, Vec *Y_loc_transpose) { 118358600ac3SJames Wright PetscFunctionBeginUser; 118458600ac3SJames Wright if (X_loc) PetscCall(VecDestroy(X_loc)); 118558600ac3SJames Wright if (Y_loc_transpose) PetscCall(VecDestroy(Y_loc_transpose)); 118658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 118758600ac3SJames Wright } 118858600ac3SJames Wright 118958600ac3SJames Wright /** 119058600ac3SJames Wright @brief Get libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 119158600ac3SJames Wright 119258600ac3SJames Wright Not collective across MPI processes. 119358600ac3SJames Wright 119458600ac3SJames Wright @param[in,out] mat MatCeed 119558600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 119658600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 119758600ac3SJames Wright 119858600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 119958600ac3SJames Wright **/ 120058600ac3SJames Wright PetscErrorCode MatCeedGetCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 120158600ac3SJames Wright MatCeedContext ctx; 120258600ac3SJames Wright 120358600ac3SJames Wright PetscFunctionBeginUser; 120458600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 120558600ac3SJames Wright if (op_mult) { 120658600ac3SJames Wright *op_mult = NULL; 120750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult, op_mult)); 120858600ac3SJames Wright } 120958600ac3SJames Wright if (op_mult_transpose) { 121058600ac3SJames Wright *op_mult_transpose = NULL; 121150f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorReferenceCopy(ctx->op_mult_transpose, op_mult_transpose)); 121258600ac3SJames Wright } 121358600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 121458600ac3SJames Wright } 121558600ac3SJames Wright 121658600ac3SJames Wright /** 121758600ac3SJames Wright @brief Restore libCEED `CeedOperator` for `MATCEED` `MatMult()` and `MatMultTranspose()` operations. 121858600ac3SJames Wright 121958600ac3SJames Wright Not collective across MPI processes. 122058600ac3SJames Wright 122158600ac3SJames Wright @param[in,out] mat MatCeed 122258600ac3SJames Wright @param[out] op_mult libCEED `CeedOperator` for `MatMult()`, or NULL 122358600ac3SJames Wright @param[out] op_mult_transpose libCEED `CeedOperator` for `MatMultTranspose()`, or NULL 122458600ac3SJames Wright 122558600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 122658600ac3SJames Wright **/ 122758600ac3SJames Wright PetscErrorCode MatCeedRestoreCeedOperators(Mat mat, CeedOperator *op_mult, CeedOperator *op_mult_transpose) { 122858600ac3SJames Wright MatCeedContext ctx; 122958600ac3SJames Wright 123058600ac3SJames Wright PetscFunctionBeginUser; 123158600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 123250f50432SJames Wright if (op_mult) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult)); 123350f50432SJames Wright if (op_mult_transpose) PetscCallCeed(ctx->ceed, CeedOperatorDestroy(op_mult_transpose)); 123458600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 123558600ac3SJames Wright } 123658600ac3SJames Wright 123758600ac3SJames Wright /** 123858600ac3SJames Wright @brief Set `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 123958600ac3SJames Wright 124058600ac3SJames Wright Not collective across MPI processes. 124158600ac3SJames Wright 124258600ac3SJames Wright @param[in,out] mat MatCeed 124358600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 124458600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 124558600ac3SJames Wright 124658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 124758600ac3SJames Wright **/ 124858600ac3SJames Wright PetscErrorCode MatCeedSetLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 124958600ac3SJames Wright MatCeedContext ctx; 125058600ac3SJames Wright 125158600ac3SJames Wright PetscFunctionBeginUser; 125258600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 125358600ac3SJames Wright if (log_event_mult) ctx->log_event_mult = log_event_mult; 125458600ac3SJames Wright if (log_event_mult_transpose) ctx->log_event_mult_transpose = log_event_mult_transpose; 125558600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 125658600ac3SJames Wright } 125758600ac3SJames Wright 125858600ac3SJames Wright /** 125958600ac3SJames Wright @brief Get `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 126058600ac3SJames Wright 126158600ac3SJames Wright Not collective across MPI processes. 126258600ac3SJames Wright 126358600ac3SJames Wright @param[in,out] mat MatCeed 126458600ac3SJames Wright @param[out] log_event_mult `PetscLogEvent` for forward evaluation, or NULL 126558600ac3SJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose evaluation, or NULL 126658600ac3SJames Wright 126758600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 126858600ac3SJames Wright **/ 126958600ac3SJames Wright PetscErrorCode MatCeedGetLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 127058600ac3SJames Wright MatCeedContext ctx; 127158600ac3SJames Wright 127258600ac3SJames Wright PetscFunctionBeginUser; 127358600ac3SJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 127458600ac3SJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_mult; 127558600ac3SJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_mult_transpose; 127658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 127758600ac3SJames Wright } 127858600ac3SJames Wright 1279c63b910fSJames Wright /** 1280c63b910fSJames Wright @brief Set `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1281c63b910fSJames Wright 1282c63b910fSJames Wright Not collective across MPI processes. 1283c63b910fSJames Wright 1284c63b910fSJames Wright @param[in,out] mat MatCeed 1285c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1286c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1287c63b910fSJames Wright 1288c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1289c63b910fSJames Wright **/ 1290c63b910fSJames Wright PetscErrorCode MatCeedSetCeedOperatorLogEvents(Mat mat, PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose) { 1291c63b910fSJames Wright MatCeedContext ctx; 1292c63b910fSJames Wright 1293c63b910fSJames Wright PetscFunctionBeginUser; 1294c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1295c63b910fSJames Wright if (log_event_mult) ctx->log_event_ceed_mult = log_event_mult; 1296c63b910fSJames Wright if (log_event_mult_transpose) ctx->log_event_ceed_mult_transpose = log_event_mult_transpose; 1297c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1298c63b910fSJames Wright } 1299c63b910fSJames Wright 1300c63b910fSJames Wright /** 1301c63b910fSJames Wright @brief Get `CeedOperator` `PetscLogEvent` for `MATCEED` `MatMult()` and `MatMultTranspose()` operators. 1302c63b910fSJames Wright 1303c63b910fSJames Wright Not collective across MPI processes. 1304c63b910fSJames Wright 1305c63b910fSJames Wright @param[in,out] mat MatCeed 1306c63b910fSJames Wright @param[out] log_event_mult `PetscLogEvent` for forward `CeedOperator` evaluation, or NULL 1307c63b910fSJames Wright @param[out] log_event_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation, or NULL 1308c63b910fSJames Wright 1309c63b910fSJames Wright @return An error code: 0 - success, otherwise - failure 1310c63b910fSJames Wright **/ 1311c63b910fSJames Wright PetscErrorCode MatCeedGetCeedOperatorLogEvents(Mat mat, PetscLogEvent *log_event_mult, PetscLogEvent *log_event_mult_transpose) { 1312c63b910fSJames Wright MatCeedContext ctx; 1313c63b910fSJames Wright 1314c63b910fSJames Wright PetscFunctionBeginUser; 1315c63b910fSJames Wright PetscCall(MatShellGetContext(mat, &ctx)); 1316c63b910fSJames Wright if (log_event_mult) *log_event_mult = ctx->log_event_ceed_mult; 1317c63b910fSJames Wright if (log_event_mult_transpose) *log_event_mult_transpose = ctx->log_event_ceed_mult_transpose; 1318c63b910fSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1319c63b910fSJames Wright } 1320c63b910fSJames Wright 132158600ac3SJames Wright // ----------------------------------------------------------------------------- 132258600ac3SJames Wright // Operator context data 132358600ac3SJames Wright // ----------------------------------------------------------------------------- 132458600ac3SJames Wright 132558600ac3SJames Wright /** 132658600ac3SJames Wright @brief Setup context data for operator application. 132758600ac3SJames Wright 132858600ac3SJames Wright Collective across MPI processes. 132958600ac3SJames Wright 133058600ac3SJames Wright @param[in] dm_x Input `DM` 133158600ac3SJames Wright @param[in] dm_y Output `DM` 133258600ac3SJames Wright @param[in] X_loc Input PETSc local vector, or NULL 133358600ac3SJames Wright @param[in] Y_loc_transpose Input PETSc local vector for transpose operation, or NULL 133458600ac3SJames Wright @param[in] op_mult `CeedOperator` for forward evaluation 133558600ac3SJames Wright @param[in] op_mult_transpose `CeedOperator` for transpose evaluation 133658600ac3SJames Wright @param[in] log_event_mult `PetscLogEvent` for forward evaluation 133758600ac3SJames Wright @param[in] log_event_mult_transpose `PetscLogEvent` for transpose evaluation 1338c63b910fSJames Wright @param[in] log_event_ceed_mult `PetscLogEvent` for forward `CeedOperator` evaluation 1339c63b910fSJames Wright @param[in] log_event_ceed_mult_transpose `PetscLogEvent` for transpose `CeedOperator` evaluation 134058600ac3SJames Wright @param[out] ctx Context data for operator evaluation 134158600ac3SJames Wright 134258600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 134358600ac3SJames Wright **/ 134458600ac3SJames Wright PetscErrorCode MatCeedContextCreate(DM dm_x, DM dm_y, Vec X_loc, Vec Y_loc_transpose, CeedOperator op_mult, CeedOperator op_mult_transpose, 1345c63b910fSJames Wright PetscLogEvent log_event_mult, PetscLogEvent log_event_mult_transpose, PetscLogEvent log_event_ceed_mult, 1346c63b910fSJames Wright PetscLogEvent log_event_ceed_mult_transpose, MatCeedContext *ctx) { 134758600ac3SJames Wright CeedSize x_loc_len, y_loc_len; 134858600ac3SJames Wright 134958600ac3SJames Wright PetscFunctionBeginUser; 135058600ac3SJames Wright 135158600ac3SJames Wright // Allocate 135258600ac3SJames Wright PetscCall(PetscNew(ctx)); 135358600ac3SJames Wright (*ctx)->ref_count = 1; 135458600ac3SJames Wright 135558600ac3SJames Wright // Logging 135658600ac3SJames Wright (*ctx)->log_event_mult = log_event_mult; 135758600ac3SJames Wright (*ctx)->log_event_mult_transpose = log_event_mult_transpose; 1358c63b910fSJames Wright (*ctx)->log_event_ceed_mult = log_event_ceed_mult; 1359c63b910fSJames Wright (*ctx)->log_event_ceed_mult_transpose = log_event_ceed_mult_transpose; 136058600ac3SJames Wright 136158600ac3SJames Wright // PETSc objects 136240d80af1SJames Wright PetscCall(DMReferenceCopy(dm_x, &(*ctx)->dm_x)); 136340d80af1SJames Wright PetscCall(DMReferenceCopy(dm_y, &(*ctx)->dm_y)); 136440d80af1SJames Wright if (X_loc) PetscCall(VecReferenceCopy(X_loc, &(*ctx)->X_loc)); 136540d80af1SJames Wright if (Y_loc_transpose) PetscCall(VecReferenceCopy(Y_loc_transpose, &(*ctx)->Y_loc_transpose)); 136658600ac3SJames Wright 136758600ac3SJames Wright // Memtype 136858600ac3SJames Wright { 136958600ac3SJames Wright const PetscScalar *x; 137058600ac3SJames Wright Vec X; 137158600ac3SJames Wright 137258600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &X)); 137358600ac3SJames Wright PetscCall(VecGetArrayReadAndMemType(X, &x, &(*ctx)->mem_type)); 137458600ac3SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X, &x)); 137558600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &X)); 137658600ac3SJames Wright } 137758600ac3SJames Wright 137858600ac3SJames Wright // libCEED objects 137958600ac3SJames Wright PetscCheck(CeedOperatorGetCeed(op_mult, &(*ctx)->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, 138058600ac3SJames Wright "retrieving Ceed context object failed"); 138150f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedReference((*ctx)->ceed)); 138250f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetActiveVectorLengths(op_mult, &x_loc_len, &y_loc_len)); 138350f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult, &(*ctx)->op_mult)); 138450f50432SJames Wright if (op_mult_transpose) PetscCallCeed((*ctx)->ceed, CeedOperatorReferenceCopy(op_mult_transpose, &(*ctx)->op_mult_transpose)); 138550f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, x_loc_len, &(*ctx)->x_loc)); 138650f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorCreate((*ctx)->ceed, y_loc_len, &(*ctx)->y_loc)); 138758600ac3SJames Wright 138858600ac3SJames Wright // Flop counting 138958600ac3SJames Wright { 139058600ac3SJames Wright CeedSize ceed_flops_estimate = 0; 139158600ac3SJames Wright 139250f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult, &ceed_flops_estimate)); 139358600ac3SJames Wright (*ctx)->flops_mult = ceed_flops_estimate; 139458600ac3SJames Wright if (op_mult_transpose) { 139550f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedOperatorGetFlopsEstimate(op_mult_transpose, &ceed_flops_estimate)); 139658600ac3SJames Wright (*ctx)->flops_mult_transpose = ceed_flops_estimate; 139758600ac3SJames Wright } 139858600ac3SJames Wright } 139958600ac3SJames Wright 140058600ac3SJames Wright // Check sizes 140158600ac3SJames Wright if (x_loc_len > 0 || y_loc_len > 0) { 140258600ac3SJames Wright CeedSize ctx_x_loc_len, ctx_y_loc_len; 140358600ac3SJames Wright PetscInt X_loc_len, dm_x_loc_len, Y_loc_len, dm_y_loc_len; 140458600ac3SJames Wright Vec dm_X_loc, dm_Y_loc; 140558600ac3SJames Wright 140658600ac3SJames Wright // -- Input 140758600ac3SJames Wright PetscCall(DMGetLocalVector(dm_x, &dm_X_loc)); 140858600ac3SJames Wright PetscCall(VecGetLocalSize(dm_X_loc, &dm_x_loc_len)); 140958600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_x, &dm_X_loc)); 141050f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->x_loc, &ctx_x_loc_len)); 14114c17272bSJames Wright if (X_loc) { 14124c17272bSJames Wright PetscCall(VecGetLocalSize(X_loc, &X_loc_len)); 14134c17272bSJames Wright PetscCheck(X_loc_len == dm_x_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 14144c17272bSJames Wright "X_loc (%" PetscInt_FMT ") must match dm_x (%" PetscInt_FMT ") dimensions", X_loc_len, dm_x_loc_len); 14154c17272bSJames Wright } 14164c17272bSJames 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", 14174c17272bSJames Wright x_loc_len, dm_x_loc_len); 14184c17272bSJames 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 ")", 14194c17272bSJames Wright x_loc_len, ctx_x_loc_len); 142058600ac3SJames Wright 142158600ac3SJames Wright // -- Output 142258600ac3SJames Wright PetscCall(DMGetLocalVector(dm_y, &dm_Y_loc)); 142358600ac3SJames Wright PetscCall(VecGetLocalSize(dm_Y_loc, &dm_y_loc_len)); 142458600ac3SJames Wright PetscCall(DMRestoreLocalVector(dm_y, &dm_Y_loc)); 142550f50432SJames Wright PetscCallCeed((*ctx)->ceed, CeedVectorGetLength((*ctx)->y_loc, &ctx_y_loc_len)); 14264c17272bSJames 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", 14274c17272bSJames Wright ctx_y_loc_len, dm_y_loc_len); 142858600ac3SJames Wright 142958600ac3SJames Wright // -- Transpose 143058600ac3SJames Wright if (Y_loc_transpose) { 143158600ac3SJames Wright PetscCall(VecGetLocalSize(Y_loc_transpose, &Y_loc_len)); 14324c17272bSJames Wright PetscCheck(Y_loc_len == dm_y_loc_len, PETSC_COMM_SELF, PETSC_ERR_LIB, 14334c17272bSJames Wright "Y_loc_transpose (%" PetscInt_FMT ") must match dm_y (%" PetscInt_FMT ") dimensions", Y_loc_len, dm_y_loc_len); 143458600ac3SJames Wright } 143558600ac3SJames Wright } 143658600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 143758600ac3SJames Wright } 143858600ac3SJames Wright 143958600ac3SJames Wright /** 144058600ac3SJames Wright @brief Increment reference counter for `MATCEED` context. 144158600ac3SJames Wright 144258600ac3SJames Wright Not collective across MPI processes. 144358600ac3SJames Wright 144458600ac3SJames Wright @param[in,out] ctx Context data 144558600ac3SJames Wright 144658600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 144758600ac3SJames Wright **/ 144858600ac3SJames Wright PetscErrorCode MatCeedContextReference(MatCeedContext ctx) { 144958600ac3SJames Wright PetscFunctionBeginUser; 145058600ac3SJames Wright ctx->ref_count++; 145158600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 145258600ac3SJames Wright } 145358600ac3SJames Wright 145458600ac3SJames Wright /** 145558600ac3SJames Wright @brief Copy reference for `MATCEED`. 145658600ac3SJames Wright Note: If `ctx_copy` is non-null, it is assumed to be a valid pointer to a `MatCeedContext`. 145758600ac3SJames Wright 145858600ac3SJames Wright Not collective across MPI processes. 145958600ac3SJames Wright 146058600ac3SJames Wright @param[in] ctx Context data 146158600ac3SJames Wright @param[out] ctx_copy Copy of pointer to context data 146258600ac3SJames Wright 146358600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 146458600ac3SJames Wright **/ 146558600ac3SJames Wright PetscErrorCode MatCeedContextReferenceCopy(MatCeedContext ctx, MatCeedContext *ctx_copy) { 146658600ac3SJames Wright PetscFunctionBeginUser; 146758600ac3SJames Wright PetscCall(MatCeedContextReference(ctx)); 146858600ac3SJames Wright PetscCall(MatCeedContextDestroy(*ctx_copy)); 146958600ac3SJames Wright *ctx_copy = ctx; 147058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 147158600ac3SJames Wright } 147258600ac3SJames Wright 147358600ac3SJames Wright /** 147458600ac3SJames Wright @brief Destroy context data for operator application. 147558600ac3SJames Wright 147658600ac3SJames Wright Collective across MPI processes. 147758600ac3SJames Wright 147858600ac3SJames Wright @param[in,out] ctx Context data for operator evaluation 147958600ac3SJames Wright 148058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 148158600ac3SJames Wright **/ 148258600ac3SJames Wright PetscErrorCode MatCeedContextDestroy(MatCeedContext ctx) { 148358600ac3SJames Wright PetscFunctionBeginUser; 148458600ac3SJames Wright if (!ctx || --ctx->ref_count > 0) PetscFunctionReturn(PETSC_SUCCESS); 148558600ac3SJames Wright 148658600ac3SJames Wright // PETSc objects 148758600ac3SJames Wright PetscCall(DMDestroy(&ctx->dm_x)); 148858600ac3SJames Wright PetscCall(DMDestroy(&ctx->dm_y)); 148958600ac3SJames Wright PetscCall(VecDestroy(&ctx->X_loc)); 149058600ac3SJames Wright PetscCall(VecDestroy(&ctx->Y_loc_transpose)); 149158600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_full_internal)); 149258600ac3SJames Wright PetscCall(MatDestroy(&ctx->mat_assembled_pbd_internal)); 149340d80af1SJames Wright PetscCall(PetscFree(ctx->coo_mat_type)); 149458600ac3SJames Wright PetscCall(PetscFree(ctx->mats_assembled_full)); 149558600ac3SJames Wright PetscCall(PetscFree(ctx->mats_assembled_pbd)); 149658600ac3SJames Wright 149758600ac3SJames Wright // libCEED objects 149850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->x_loc)); 149950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->y_loc)); 150050f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->coo_values_full)); 150150f50432SJames Wright PetscCallCeed(ctx->ceed, CeedVectorDestroy(&ctx->coo_values_pbd)); 150250f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorDestroy(&ctx->op_mult)); 150350f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorDestroy(&ctx->op_mult_transpose)); 150458600ac3SJames Wright PetscCheck(CeedDestroy(&ctx->ceed) == CEED_ERROR_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_LIB, "destroying libCEED context object failed"); 150558600ac3SJames Wright 150658600ac3SJames Wright // Deallocate 150758600ac3SJames Wright ctx->is_destroyed = PETSC_TRUE; // Flag as destroyed in case someone has stale ref 150858600ac3SJames Wright PetscCall(PetscFree(ctx)); 150958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 151058600ac3SJames Wright } 151158600ac3SJames Wright 151258600ac3SJames Wright /** 151358600ac3SJames Wright @brief Compute the diagonal of an operator via libCEED. 151458600ac3SJames Wright 151558600ac3SJames Wright Collective across MPI processes. 151658600ac3SJames Wright 151758600ac3SJames Wright @param[in] A `MATCEED` 151858600ac3SJames Wright @param[out] D Vector holding operator diagonal 151958600ac3SJames Wright 152058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 152158600ac3SJames Wright **/ 152258600ac3SJames Wright PetscErrorCode MatGetDiagonal_Ceed(Mat A, Vec D) { 152358600ac3SJames Wright PetscMemType mem_type; 152458600ac3SJames Wright Vec D_loc; 152558600ac3SJames Wright MatCeedContext ctx; 152658600ac3SJames Wright 152758600ac3SJames Wright PetscFunctionBeginUser; 152858600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 152958600ac3SJames Wright 153058600ac3SJames Wright // Place PETSc vector in libCEED vector 1531c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 153258600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &D_loc)); 1533a7dac1d5SJames Wright PetscCall(VecPetscToCeed(D_loc, &mem_type, ctx->x_loc)); 153458600ac3SJames Wright 153558600ac3SJames Wright // Compute Diagonal 1536c63b910fSJames Wright PetscCall(PetscLogEventBegin(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 153750f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorLinearAssembleDiagonal(ctx->op_mult, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 1538c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL_CEEDOP, A, D, NULL, NULL)); 153958600ac3SJames Wright 154058600ac3SJames Wright // Restore PETSc vector 1541a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, mem_type, D_loc)); 154258600ac3SJames Wright 154358600ac3SJames Wright // Local-to-Global 154458600ac3SJames Wright PetscCall(VecZeroEntries(D)); 154558600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, D_loc, ADD_VALUES, D)); 154658600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &D_loc)); 1547c63b910fSJames Wright PetscCall(PetscLogEventEnd(MATCEED_ASSEMBLE_DIAGONAL, A, D, NULL, NULL)); 154858600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 154958600ac3SJames Wright } 155058600ac3SJames Wright 155158600ac3SJames Wright /** 155258600ac3SJames Wright @brief Compute `A X = Y` for a `MATCEED`. 155358600ac3SJames Wright 155458600ac3SJames Wright Collective across MPI processes. 155558600ac3SJames Wright 155658600ac3SJames Wright @param[in] A `MATCEED` 155758600ac3SJames Wright @param[in] X Input PETSc vector 155858600ac3SJames Wright @param[out] Y Output PETSc vector 155958600ac3SJames Wright 156058600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 156158600ac3SJames Wright **/ 156258600ac3SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 156358600ac3SJames Wright MatCeedContext ctx; 156458600ac3SJames Wright 156558600ac3SJames Wright PetscFunctionBeginUser; 156658600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1567c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult, A, X, Y, NULL)); 156858600ac3SJames Wright 156958600ac3SJames Wright { 157058600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 157158600ac3SJames Wright Vec X_loc = ctx->X_loc, Y_loc; 157258600ac3SJames Wright 157358600ac3SJames Wright // Get local vectors 157458600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 157558600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 157658600ac3SJames Wright 157758600ac3SJames Wright // Global-to-local 157858600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc)); 157958600ac3SJames Wright 158058600ac3SJames Wright // Setup libCEED vectors 1581a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 158258600ac3SJames Wright PetscCall(VecZeroEntries(Y_loc)); 1583a7dac1d5SJames Wright PetscCall(VecPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 158458600ac3SJames Wright 158558600ac3SJames Wright // Apply libCEED operator 1586c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult, A, X, Y, NULL)); 1587537ec908SJames Wright PetscCall(PetscLogGpuTimeBegin()); 158850f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult, ctx->x_loc, ctx->y_loc, CEED_REQUEST_IMMEDIATE)); 158958600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1590537ec908SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult, A, X, Y, NULL)); 159158600ac3SJames Wright 159258600ac3SJames Wright // Restore PETSc vectors 1593a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 1594a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 159558600ac3SJames Wright 159658600ac3SJames Wright // Local-to-global 159758600ac3SJames Wright PetscCall(VecZeroEntries(Y)); 159858600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y)); 159958600ac3SJames Wright 160058600ac3SJames Wright // Restore local vectors, as needed 160158600ac3SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 160258600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 160358600ac3SJames Wright } 160458600ac3SJames Wright 160558600ac3SJames Wright // Log flops 160658600ac3SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult)); 160758600ac3SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult)); 1608c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult, A, X, Y, NULL)); 160958600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 161058600ac3SJames Wright } 161158600ac3SJames Wright 161258600ac3SJames Wright /** 161358600ac3SJames Wright @brief Compute `A^T Y = X` for a `MATCEED`. 161458600ac3SJames Wright 161558600ac3SJames Wright Collective across MPI processes. 161658600ac3SJames Wright 161758600ac3SJames Wright @param[in] A `MATCEED` 161858600ac3SJames Wright @param[in] Y Input PETSc vector 161958600ac3SJames Wright @param[out] X Output PETSc vector 162058600ac3SJames Wright 162158600ac3SJames Wright @return An error code: 0 - success, otherwise - failure 162258600ac3SJames Wright **/ 162358600ac3SJames Wright PetscErrorCode MatMultTranspose_Ceed(Mat A, Vec Y, Vec X) { 162458600ac3SJames Wright MatCeedContext ctx; 162558600ac3SJames Wright 162658600ac3SJames Wright PetscFunctionBeginUser; 162758600ac3SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 1628c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_mult_transpose, A, Y, X, NULL)); 162958600ac3SJames Wright 163058600ac3SJames Wright { 163158600ac3SJames Wright PetscMemType x_mem_type, y_mem_type; 163258600ac3SJames Wright Vec X_loc, Y_loc = ctx->Y_loc_transpose; 163358600ac3SJames Wright 163458600ac3SJames Wright // Get local vectors 163558600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 163658600ac3SJames Wright PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 163758600ac3SJames Wright 163858600ac3SJames Wright // Global-to-local 163958600ac3SJames Wright PetscCall(DMGlobalToLocal(ctx->dm_y, Y, INSERT_VALUES, Y_loc)); 164058600ac3SJames Wright 164158600ac3SJames Wright // Setup libCEED vectors 1642a7dac1d5SJames Wright PetscCall(VecReadPetscToCeed(Y_loc, &y_mem_type, ctx->y_loc)); 164358600ac3SJames Wright PetscCall(VecZeroEntries(X_loc)); 1644a7dac1d5SJames Wright PetscCall(VecPetscToCeed(X_loc, &x_mem_type, ctx->x_loc)); 164558600ac3SJames Wright 164658600ac3SJames Wright // Apply libCEED operator 1647c63b910fSJames Wright PetscCall(PetscLogEventBegin(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 1648537ec908SJames Wright PetscCall(PetscLogGpuTimeBegin()); 164950f50432SJames Wright PetscCallCeed(ctx->ceed, CeedOperatorApplyAdd(ctx->op_mult_transpose, ctx->y_loc, ctx->x_loc, CEED_REQUEST_IMMEDIATE)); 165058600ac3SJames Wright PetscCall(PetscLogGpuTimeEnd()); 1651537ec908SJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_ceed_mult_transpose, A, Y, X, NULL)); 165258600ac3SJames Wright 165358600ac3SJames Wright // Restore PETSc vectors 1654a7dac1d5SJames Wright PetscCall(VecReadCeedToPetsc(ctx->y_loc, y_mem_type, Y_loc)); 1655a7dac1d5SJames Wright PetscCall(VecCeedToPetsc(ctx->x_loc, x_mem_type, X_loc)); 165658600ac3SJames Wright 165758600ac3SJames Wright // Local-to-global 165858600ac3SJames Wright PetscCall(VecZeroEntries(X)); 165958600ac3SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_x, X_loc, ADD_VALUES, X)); 166058600ac3SJames Wright 166158600ac3SJames Wright // Restore local vectors, as needed 166258600ac3SJames Wright if (!ctx->Y_loc_transpose) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 166358600ac3SJames Wright PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 166458600ac3SJames Wright } 166558600ac3SJames Wright 166658600ac3SJames Wright // Log flops 166758600ac3SJames Wright if (PetscMemTypeDevice(ctx->mem_type)) PetscCall(PetscLogGpuFlops(ctx->flops_mult_transpose)); 166858600ac3SJames Wright else PetscCall(PetscLogFlops(ctx->flops_mult_transpose)); 1669c63b910fSJames Wright PetscCall(PetscLogEventEnd(ctx->log_event_mult_transpose, A, Y, X, NULL)); 167058600ac3SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 167158600ac3SJames Wright } 1672