1f7325489SJames Wright // Copyright (c) 2017-2023, Lawrence Livermore National Security, LLC and other CEED contributors. 2f7325489SJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3f7325489SJames Wright // 4f7325489SJames Wright // SPDX-License-Identifier: BSD-2-Clause 5f7325489SJames Wright // 6f7325489SJames Wright // This file is part of CEED: http://github.com/ceed 7f7325489SJames Wright 8f7325489SJames Wright #include "../include/petsc_ops.h" 9f7325489SJames Wright 10f7325489SJames Wright #include <ceed.h> 11f7325489SJames Wright #include <petscdm.h> 12f7325489SJames Wright 13f7325489SJames Wright #include "../navierstokes.h" 14f7325489SJames Wright 15*fbcfc4fcSJames Wright /** 16*fbcfc4fcSJames Wright * @brief Create OperatorApplyContext struct for applying FEM operator in a PETSc context 17*fbcfc4fcSJames Wright * 18*fbcfc4fcSJames Wright * All passed in objects are reference copied and may be destroyed if desired (with the exception of `CEED_VECTOR_NONE`). 19*fbcfc4fcSJames Wright * Resulting context should be destroyed with `OperatorApplyContextDestroy()`. 20*fbcfc4fcSJames Wright * 21*fbcfc4fcSJames Wright * @param[in] dm_x `DM` associated with the operator active input. May be `NULL` 22*fbcfc4fcSJames Wright * @param[in] dm_y `DM` associated with the operator active output. May be `NULL` 23*fbcfc4fcSJames Wright * @param[in] ceed `Ceed` object 24*fbcfc4fcSJames Wright * @param[in] op_apply `CeedOperator` representing the local action of the FEM operator 25*fbcfc4fcSJames Wright * @param[in] x_ceed `CeedVector` for operator active input. May be `CEED_VECTOR_NONE` or `NULL`. If `NULL`, `CeedVector` will be automatically 26*fbcfc4fcSJames Wright * generated. 27*fbcfc4fcSJames Wright * @param[in] y_ceed `CeedVector` for operator active output. May be `CEED_VECTOR_NONE` or `NULL`. If `NULL`, `CeedVector` will be automatically 28*fbcfc4fcSJames Wright * generated. 29*fbcfc4fcSJames Wright * @param[in] X_loc Local `Vec` for operator active input. If `NULL`, vector will be obtained if needed at ApplyCeedOperator time. 30*fbcfc4fcSJames Wright * @param[in] Y_loc Local `Vec` for operator active output. If `NULL`, vector will be obtained if needed at ApplyCeedOperator time. 31*fbcfc4fcSJames Wright * @param[out] ctx Struct containing all data necessary for applying the operator 32*fbcfc4fcSJames Wright */ 33f7325489SJames Wright PetscErrorCode OperatorApplyContextCreate(DM dm_x, DM dm_y, Ceed ceed, CeedOperator op_apply, CeedVector x_ceed, CeedVector y_ceed, Vec X_loc, 34*fbcfc4fcSJames Wright Vec Y_loc, OperatorApplyContext *ctx) { 35f7325489SJames Wright CeedSize x_size, y_size; 36*fbcfc4fcSJames Wright 37*fbcfc4fcSJames Wright PetscFunctionBeginUser; 38f7325489SJames Wright CeedOperatorGetActiveVectorLengths(op_apply, &x_size, &y_size); 39*fbcfc4fcSJames Wright { // Verify sizes 40*fbcfc4fcSJames Wright PetscInt X_size, Y_size; 41f7325489SJames Wright if (X_loc) { 42f7325489SJames Wright PetscCall(VecGetLocalSize(X_loc, &X_size)); 43f7325489SJames Wright PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, 44f7325489SJames Wright "X_loc (%" PetscInt_FMT ") not correct size for CeedOperator active input size (%" CeedSize_FMT ")", X_size, x_size); 45f7325489SJames Wright } 46f7325489SJames Wright if (Y_loc) { 47f7325489SJames Wright PetscCall(VecGetLocalSize(Y_loc, &Y_size)); 48f7325489SJames Wright PetscCheck(Y_size == y_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, 49f7325489SJames Wright "Y_loc (%" PetscInt_FMT ") not correct size for CeedOperator active output size (%" CeedSize_FMT ")", Y_size, y_size); 50f7325489SJames Wright } 51f7325489SJames Wright } 52f7325489SJames Wright 53*fbcfc4fcSJames Wright PetscCall(PetscNew(ctx)); 54f7325489SJames Wright 55f7325489SJames Wright // Copy PETSc Objects 56f7325489SJames Wright if (dm_x) PetscCall(PetscObjectReference((PetscObject)dm_x)); 57*fbcfc4fcSJames Wright (*ctx)->dm_x = dm_x; 58f7325489SJames Wright if (dm_y) PetscCall(PetscObjectReference((PetscObject)dm_y)); 59*fbcfc4fcSJames Wright (*ctx)->dm_y = dm_y; 60f7325489SJames Wright 61f7325489SJames Wright if (X_loc) PetscCall(PetscObjectReference((PetscObject)X_loc)); 62*fbcfc4fcSJames Wright (*ctx)->X_loc = X_loc; 63f7325489SJames Wright if (Y_loc) PetscCall(PetscObjectReference((PetscObject)Y_loc)); 64*fbcfc4fcSJames Wright (*ctx)->Y_loc = Y_loc; 65f7325489SJames Wright 66f7325489SJames Wright // Copy libCEED objects 67*fbcfc4fcSJames Wright if (x_ceed) CeedVectorReferenceCopy(x_ceed, &(*ctx)->x_ceed); 68*fbcfc4fcSJames Wright else CeedVectorCreate(ceed, x_size, &(*ctx)->x_ceed); 69*fbcfc4fcSJames Wright 70*fbcfc4fcSJames Wright if (y_ceed) CeedVectorReferenceCopy(y_ceed, &(*ctx)->y_ceed); 71*fbcfc4fcSJames Wright else CeedVectorCreate(ceed, y_size, &(*ctx)->y_ceed); 72*fbcfc4fcSJames Wright 73*fbcfc4fcSJames Wright CeedOperatorReferenceCopy(op_apply, &(*ctx)->op); 74*fbcfc4fcSJames Wright CeedReferenceCopy(ceed, &(*ctx)->ceed); 75f7325489SJames Wright 76f7325489SJames Wright PetscFunctionReturn(0); 77f7325489SJames Wright } 78f7325489SJames Wright 79*fbcfc4fcSJames Wright /** 80*fbcfc4fcSJames Wright * @brief Destroy OperatorApplyContext struct 81*fbcfc4fcSJames Wright * 82*fbcfc4fcSJames Wright * @param[in,out] ctx Context to destroy 83*fbcfc4fcSJames Wright */ 84*fbcfc4fcSJames Wright PetscErrorCode OperatorApplyContextDestroy(OperatorApplyContext ctx) { 85f7325489SJames Wright PetscFunctionBeginUser; 86f7325489SJames Wright 87*fbcfc4fcSJames Wright if (!ctx) PetscFunctionReturn(0); 88f7325489SJames Wright 89f7325489SJames Wright // Destroy PETSc Objects 90*fbcfc4fcSJames Wright PetscCall(DMDestroy(&ctx->dm_x)); 91*fbcfc4fcSJames Wright PetscCall(DMDestroy(&ctx->dm_y)); 92*fbcfc4fcSJames Wright PetscCall(VecDestroy(&ctx->X_loc)); 93*fbcfc4fcSJames Wright PetscCall(VecDestroy(&ctx->Y_loc)); 94f7325489SJames Wright 95f7325489SJames Wright // Destroy libCEED Objects 96*fbcfc4fcSJames Wright CeedVectorDestroy(&ctx->x_ceed); 97*fbcfc4fcSJames Wright CeedVectorDestroy(&ctx->y_ceed); 98*fbcfc4fcSJames Wright CeedOperatorDestroy(&ctx->op); 99*fbcfc4fcSJames Wright CeedDestroy(&ctx->ceed); 100f7325489SJames Wright 101*fbcfc4fcSJames Wright PetscCall(PetscFree(ctx)); 102f7325489SJames Wright 103f7325489SJames Wright PetscFunctionReturn(0); 104f7325489SJames Wright } 105f7325489SJames Wright 106f7325489SJames Wright /** 107f7325489SJames Wright @brief Transfer array from PETSc Vec to CeedVector 108f7325489SJames Wright 109f7325489SJames Wright @param[in] X_petsc PETSc Vec 110f7325489SJames Wright @param[out] mem_type PETSc MemType 111f7325489SJames Wright @param[out] x_ceed CeedVector 112f7325489SJames Wright 113f7325489SJames Wright @return An error code: 0 - success, otherwise - failure 114f7325489SJames Wright **/ 115f7325489SJames Wright PetscErrorCode VecP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) { 116f7325489SJames Wright PetscScalar *x; 117f7325489SJames Wright PetscInt X_size; 118f7325489SJames Wright CeedSize x_size; 119f7325489SJames Wright 120f7325489SJames Wright PetscFunctionBeginUser; 121f7325489SJames Wright PetscCall(VecGetLocalSize(X_petsc, &X_size)); 122f7325489SJames Wright CeedVectorGetLength(x_ceed, &x_size); 123f7325489SJames Wright PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, "X_petsc (%" PetscInt_FMT ") and x_ceed (%" CeedSize_FMT ") must be same size", 124f7325489SJames Wright X_size, x_size); 125f7325489SJames Wright 126f7325489SJames Wright PetscCall(VecGetArrayAndMemType(X_petsc, &x, mem_type)); 127f7325489SJames Wright CeedVectorSetArray(x_ceed, MemTypeP2C(*mem_type), CEED_USE_POINTER, x); 128f7325489SJames Wright 129f7325489SJames Wright PetscFunctionReturn(0); 130f7325489SJames Wright } 131f7325489SJames Wright 132f7325489SJames Wright /** 133f7325489SJames Wright @brief Transfer array from CeedVector to PETSc Vec 134f7325489SJames Wright 135f7325489SJames Wright @param[in] x_ceed CeedVector 136f7325489SJames Wright @param[in] mem_type PETSc MemType 137f7325489SJames Wright @param[out] X_petsc PETSc Vec 138f7325489SJames Wright 139f7325489SJames Wright @return An error code: 0 - success, otherwise - failure 140f7325489SJames Wright **/ 141f7325489SJames Wright PetscErrorCode VecC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) { 142f7325489SJames Wright PetscScalar *x; 143f7325489SJames Wright PetscInt X_size; 144f7325489SJames Wright CeedSize x_size; 145f7325489SJames Wright 146f7325489SJames Wright PetscFunctionBeginUser; 147f7325489SJames Wright PetscCall(VecGetLocalSize(X_petsc, &X_size)); 148f7325489SJames Wright CeedVectorGetLength(x_ceed, &x_size); 149f7325489SJames Wright PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, "X_petsc (%" PetscInt_FMT ") and x_ceed (%" CeedSize_FMT ") must be same size", 150f7325489SJames Wright X_size, x_size); 151f7325489SJames Wright 152f7325489SJames Wright CeedVectorTakeArray(x_ceed, MemTypeP2C(mem_type), &x); 153f7325489SJames Wright PetscCall(VecRestoreArrayAndMemType(X_petsc, &x)); 154f7325489SJames Wright 155f7325489SJames Wright PetscFunctionReturn(0); 156f7325489SJames Wright } 157f7325489SJames Wright 158f7325489SJames Wright /** 159f7325489SJames Wright @brief Transfer read-only array from PETSc Vec to CeedVector 160f7325489SJames Wright 161f7325489SJames Wright @param[in] X_petsc PETSc Vec 162f7325489SJames Wright @param[out] mem_type PETSc MemType 163f7325489SJames Wright @param[out] x_ceed CeedVector 164f7325489SJames Wright 165f7325489SJames Wright @return An error code: 0 - success, otherwise - failure 166f7325489SJames Wright **/ 167f7325489SJames Wright PetscErrorCode VecReadP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) { 168f7325489SJames Wright PetscScalar *x; 169f7325489SJames Wright PetscInt X_size; 170f7325489SJames Wright CeedSize x_size; 171f7325489SJames Wright 172f7325489SJames Wright PetscFunctionBeginUser; 173f7325489SJames Wright PetscCall(VecGetLocalSize(X_petsc, &X_size)); 174f7325489SJames Wright CeedVectorGetLength(x_ceed, &x_size); 175f7325489SJames Wright PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, "X_petsc (%" PetscInt_FMT ") and x_ceed (%" CeedSize_FMT ") must be same size", 176f7325489SJames Wright X_size, x_size); 177f7325489SJames Wright 178f7325489SJames Wright PetscCall(VecGetArrayReadAndMemType(X_petsc, (const PetscScalar **)&x, mem_type)); 179f7325489SJames Wright CeedVectorSetArray(x_ceed, MemTypeP2C(*mem_type), CEED_USE_POINTER, x); 180f7325489SJames Wright 181f7325489SJames Wright PetscFunctionReturn(0); 182f7325489SJames Wright } 183f7325489SJames Wright 184f7325489SJames Wright /** 185f7325489SJames Wright @brief Transfer read-only array from CeedVector to PETSc Vec 186f7325489SJames Wright 187f7325489SJames Wright @param[in] x_ceed CeedVector 188f7325489SJames Wright @param[in] mem_type PETSc MemType 189f7325489SJames Wright @param[out] X_petsc PETSc Vec 190f7325489SJames Wright 191f7325489SJames Wright @return An error code: 0 - success, otherwise - failure 192f7325489SJames Wright **/ 193f7325489SJames Wright PetscErrorCode VecReadC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) { 194f7325489SJames Wright PetscScalar *x; 195f7325489SJames Wright PetscInt X_size; 196f7325489SJames Wright CeedSize x_size; 197f7325489SJames Wright 198f7325489SJames Wright PetscFunctionBeginUser; 199f7325489SJames Wright PetscCall(VecGetLocalSize(X_petsc, &X_size)); 200f7325489SJames Wright CeedVectorGetLength(x_ceed, &x_size); 201f7325489SJames Wright PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, "X_petsc (%" PetscInt_FMT ") and x_ceed (%" CeedSize_FMT ") must be same size", 202f7325489SJames Wright X_size, x_size); 203f7325489SJames Wright 204f7325489SJames Wright CeedVectorTakeArray(x_ceed, MemTypeP2C(mem_type), &x); 205f7325489SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X_petsc, (const PetscScalar **)&x)); 206f7325489SJames Wright 207f7325489SJames Wright PetscFunctionReturn(0); 208f7325489SJames Wright } 209f7325489SJames Wright 210f7325489SJames Wright /** 211f7325489SJames Wright @brief Copy PETSc Vec data into CeedVector 212f7325489SJames Wright 213f7325489SJames Wright @param[in] X_petsc PETSc Vec 214f7325489SJames Wright @param[out] x_ceed CeedVector 215f7325489SJames Wright 216f7325489SJames Wright @return An error code: 0 - success, otherwise - failure 217f7325489SJames Wright **/ 218f7325489SJames Wright PetscErrorCode VecCopyP2C(Vec X_petsc, CeedVector x_ceed) { 219f7325489SJames Wright PetscScalar *x; 220f7325489SJames Wright PetscMemType mem_type; 221f7325489SJames Wright PetscInt X_size; 222f7325489SJames Wright CeedSize x_size; 223f7325489SJames Wright 224f7325489SJames Wright PetscFunctionBeginUser; 225f7325489SJames Wright PetscCall(VecGetLocalSize(X_petsc, &X_size)); 226f7325489SJames Wright CeedVectorGetLength(x_ceed, &x_size); 227f7325489SJames Wright PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, "X_petsc (%" PetscInt_FMT ") and x_ceed (%" CeedSize_FMT ") must be same size", 228f7325489SJames Wright X_size, x_size); 229f7325489SJames Wright 230f7325489SJames Wright PetscCall(VecGetArrayReadAndMemType(X_petsc, (const PetscScalar **)&x, &mem_type)); 231f7325489SJames Wright CeedVectorSetArray(x_ceed, MemTypeP2C(mem_type), CEED_COPY_VALUES, x); 232f7325489SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X_petsc, (const PetscScalar **)&x)); 233f7325489SJames Wright 234f7325489SJames Wright PetscFunctionReturn(0); 235f7325489SJames Wright } 236f7325489SJames Wright 2376cbc221eSJames Wright //@brief Return VecType for the given DM 2386cbc221eSJames Wright VecType DMReturnVecType(DM dm) { 2396cbc221eSJames Wright VecType vec_type; 2406cbc221eSJames Wright DMGetVecType(dm, &vec_type); 2416cbc221eSJames Wright return vec_type; 2426cbc221eSJames Wright } 2436cbc221eSJames Wright 2446cbc221eSJames Wright /** 2456cbc221eSJames Wright * @brief Create local PETSc Vecs for CeedOperator's active input/outputs 2466cbc221eSJames Wright * 2476cbc221eSJames Wright * This is primarily used for when the active input/ouput vector does not correspond to a `DM` object, and thus `DMCreateLocalVector` or 2486cbc221eSJames Wright * `DMGetLocalVector` are not applicable. 2496cbc221eSJames Wright * For example, if statitics are being store at quadrature points, a `DM`-created `Vec` will not have the 2506cbc221eSJames Wright * correct size. 2516cbc221eSJames Wright * 2526cbc221eSJames Wright * @param[in] dm DM overwhich the Vecs would be used 2536cbc221eSJames Wright * @param[in] op Operator to make the Vecs for 2546cbc221eSJames Wright * @param[out] input Vec for CeedOperator active input 2556cbc221eSJames Wright * @param[out] output Vec for CeedOperator active output 2566cbc221eSJames Wright */ 2576cbc221eSJames Wright PetscErrorCode CeedOperatorCreateLocalVecs(CeedOperator op, VecType vec_type, MPI_Comm comm, Vec *input, Vec *output) { 2586cbc221eSJames Wright CeedSize input_size, output_size; 2596cbc221eSJames Wright 2606cbc221eSJames Wright PetscFunctionBeginUser; 2616cbc221eSJames Wright CeedOperatorGetActiveVectorLengths(op, &input_size, &output_size); 2626cbc221eSJames Wright if (input) { 2636cbc221eSJames Wright PetscCall(VecCreate(comm, input)); 2646cbc221eSJames Wright PetscCall(VecSetType(*input, vec_type)); 2656cbc221eSJames Wright PetscCall(VecSetSizes(*input, input_size, input_size)); 2666cbc221eSJames Wright } 2676cbc221eSJames Wright if (output) { 2686cbc221eSJames Wright PetscCall(VecCreate(comm, output)); 2696cbc221eSJames Wright PetscCall(VecSetType(*output, vec_type)); 2706cbc221eSJames Wright PetscCall(VecSetSizes(*output, output_size, output_size)); 2716cbc221eSJames Wright } 2726cbc221eSJames Wright 2736cbc221eSJames Wright PetscFunctionReturn(0); 2746cbc221eSJames Wright } 2756cbc221eSJames Wright 276f7325489SJames Wright /** 277f7325489SJames Wright * @brief Apply FEM Operator defined by `OperatorApplyContext` to various input and output vectors 278f7325489SJames Wright * 279f7325489SJames Wright * @param X Input global `Vec`, maybe `NULL` 280f7325489SJames Wright * @param X_loc Input local `Vec`, maybe `NULL` 281f7325489SJames Wright * @param x_ceed Input `CeedVector`, maybe `CEED_VECTOR_NONE` 282f7325489SJames Wright * @param y_ceed Output `CeedVector`, maybe `CEED_VECTOR_NONE` 283f7325489SJames Wright * @param Y_loc Output local `Vec`, maybe `NULL` 284f7325489SJames Wright * @param Y Output global `Vec`, maybe `NULL` 285f7325489SJames Wright * @param ctx Context for the operator apply 286f7325489SJames Wright * @param use_apply_add Whether to use `CeedOperatorApply` or `CeedOperatorApplyAdd` 287f7325489SJames Wright */ 288f7325489SJames Wright PetscErrorCode ApplyCeedOperator_Core(Vec X, Vec X_loc, CeedVector x_ceed, CeedVector y_ceed, Vec Y_loc, Vec Y, OperatorApplyContext ctx, 289f7325489SJames Wright bool use_apply_add) { 290f7325489SJames Wright PetscMemType x_mem_type, y_mem_type; 291f7325489SJames Wright 292f7325489SJames Wright PetscFunctionBeginUser; 293f7325489SJames Wright if (X) PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc)); 294f7325489SJames Wright if (X_loc) PetscCall(VecReadP2C(X_loc, &x_mem_type, x_ceed)); 295f7325489SJames Wright 296f7325489SJames Wright if (Y_loc) PetscCall(VecP2C(Y_loc, &y_mem_type, y_ceed)); 297f7325489SJames Wright 298f7325489SJames Wright if (use_apply_add) CeedOperatorApplyAdd(ctx->op, x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE); 299f7325489SJames Wright else CeedOperatorApply(ctx->op, x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE); 300f7325489SJames Wright 301f7325489SJames Wright if (X_loc) PetscCall(VecReadC2P(ctx->x_ceed, x_mem_type, X_loc)); 302f7325489SJames Wright 303f7325489SJames Wright if (Y_loc) PetscCall(VecC2P(ctx->y_ceed, y_mem_type, Y_loc)); 304f7325489SJames Wright if (Y) PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y)); 305f7325489SJames Wright 306f7325489SJames Wright PetscFunctionReturn(0); 307f7325489SJames Wright }; 308f7325489SJames Wright 309f7325489SJames Wright PetscErrorCode ApplyCeedOperatorGlobalToGlobal(Vec X, Vec Y, OperatorApplyContext ctx) { 310f7325489SJames Wright Vec X_loc = ctx->X_loc, Y_loc = ctx->Y_loc; 311f7325489SJames Wright 312f7325489SJames Wright PetscFunctionBeginUser; 313f7325489SJames Wright PetscCall(VecZeroEntries(Y)); 314f7325489SJames Wright 315f7325489SJames Wright // Get local vectors (if needed) 316f7325489SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 317f7325489SJames Wright if (!ctx->Y_loc) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 318f7325489SJames Wright 319f7325489SJames Wright PetscCall(ApplyCeedOperator_Core(X, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, Y, ctx, false)); 320f7325489SJames Wright 321f7325489SJames Wright // Restore local vector (if needed) 322f7325489SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 323f7325489SJames Wright if (!ctx->Y_loc) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 324f7325489SJames Wright 325f7325489SJames Wright PetscFunctionReturn(0); 326f7325489SJames Wright } 327f7325489SJames Wright 328f7325489SJames Wright PetscErrorCode ApplyCeedOperatorLocalToGlobal(Vec X_loc, Vec Y, OperatorApplyContext ctx) { 329f7325489SJames Wright Vec Y_loc = ctx->Y_loc; 330f7325489SJames Wright 331f7325489SJames Wright PetscFunctionBeginUser; 332f7325489SJames Wright PetscCall(VecZeroEntries(Y)); 333f7325489SJames Wright 334f7325489SJames Wright // Get local vectors (if needed) 335f7325489SJames Wright if (!ctx->Y_loc) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 336f7325489SJames Wright 337f7325489SJames Wright PetscCall(ApplyCeedOperator_Core(NULL, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, Y, ctx, false)); 338f7325489SJames Wright 339f7325489SJames Wright // Restore local vectors (if needed) 340f7325489SJames Wright if (!ctx->Y_loc) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 341f7325489SJames Wright 342f7325489SJames Wright PetscFunctionReturn(0); 343f7325489SJames Wright } 344f7325489SJames Wright 345f7325489SJames Wright PetscErrorCode ApplyCeedOperatorGlobalToLocal(Vec X, Vec Y_loc, OperatorApplyContext ctx) { 346f7325489SJames Wright Vec X_loc = ctx->X_loc; 347f7325489SJames Wright 348f7325489SJames Wright PetscFunctionBeginUser; 349f7325489SJames Wright // Get local vectors (if needed) 350f7325489SJames Wright if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc)); 351f7325489SJames Wright 352f7325489SJames Wright PetscCall(ApplyCeedOperator_Core(X, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, NULL, ctx, false)); 353f7325489SJames Wright 354f7325489SJames Wright // Restore local vector (if needed) 355f7325489SJames Wright if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc)); 356f7325489SJames Wright 357f7325489SJames Wright PetscFunctionReturn(0); 358f7325489SJames Wright } 359f7325489SJames Wright 360f7325489SJames Wright PetscErrorCode ApplyAddCeedOperatorLocalToLocal(Vec X_loc, Vec Y_loc, OperatorApplyContext ctx) { 361f7325489SJames Wright PetscFunctionBeginUser; 362f7325489SJames Wright PetscCall(ApplyCeedOperator_Core(NULL, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, NULL, ctx, true)); 363f7325489SJames Wright PetscFunctionReturn(0); 364f7325489SJames Wright } 365f7325489SJames Wright 366f7325489SJames Wright // ----------------------------------------------------------------------------- 367f7325489SJames Wright // Wraps the libCEED operator for a MatShell 368f7325489SJames Wright // ----------------------------------------------------------------------------- 369f7325489SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 370f7325489SJames Wright OperatorApplyContext ctx; 371f7325489SJames Wright PetscFunctionBeginUser; 372f7325489SJames Wright 373f7325489SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 374f7325489SJames Wright PetscCall(ApplyCeedOperatorGlobalToGlobal(X, Y, ctx)); 375f7325489SJames Wright 376f7325489SJames Wright PetscFunctionReturn(0); 377f7325489SJames Wright }; 378f7325489SJames Wright 379f7325489SJames Wright // ----------------------------------------------------------------------------- 380f7325489SJames Wright // Returns the computed diagonal of the operator 381f7325489SJames Wright // ----------------------------------------------------------------------------- 382f7325489SJames Wright PetscErrorCode MatGetDiag_Ceed(Mat A, Vec D) { 383f7325489SJames Wright OperatorApplyContext ctx; 384f7325489SJames Wright Vec Y_loc; 385f7325489SJames Wright PetscMemType mem_type; 386f7325489SJames Wright PetscFunctionBeginUser; 387f7325489SJames Wright 388f7325489SJames Wright PetscCall(MatShellGetContext(A, &ctx)); 389f7325489SJames Wright if (ctx->Y_loc) Y_loc = ctx->Y_loc; 390f7325489SJames Wright else PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc)); 391f7325489SJames Wright 392f7325489SJames Wright // -- Place PETSc vector in libCEED vector 393f7325489SJames Wright PetscCall(VecP2C(Y_loc, &mem_type, ctx->y_ceed)); 394f7325489SJames Wright 395f7325489SJames Wright // -- Compute Diagonal 396f7325489SJames Wright CeedOperatorLinearAssembleDiagonal(ctx->op, ctx->y_ceed, CEED_REQUEST_IMMEDIATE); 397f7325489SJames Wright 398f7325489SJames Wright // -- Local-to-Global 399f7325489SJames Wright PetscCall(VecC2P(ctx->y_ceed, mem_type, Y_loc)); 400f7325489SJames Wright PetscCall(VecZeroEntries(D)); 401f7325489SJames Wright PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, D)); 402f7325489SJames Wright 403f7325489SJames Wright if (!ctx->Y_loc) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc)); 404f7325489SJames Wright PetscFunctionReturn(0); 405f7325489SJames Wright }; 406f7325489SJames Wright 407f7325489SJames Wright // ----------------------------------------------------------------------------- 408