xref: /honee/src/petsc_ops.c (revision 6cbc221e08f36ca553e7bfe766a8cbdb252ad96a)
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 
15f7325489SJames Wright // -----------------------------------------------------------------------------
16f7325489SJames Wright // Setup apply operator context data
17f7325489SJames Wright // -----------------------------------------------------------------------------
18f7325489SJames Wright PetscErrorCode OperatorApplyContextCreate(DM dm_x, DM dm_y, Ceed ceed, CeedOperator op_apply, CeedVector x_ceed, CeedVector y_ceed, Vec X_loc,
19f7325489SJames Wright                                           Vec Y_loc, OperatorApplyContext *op_apply_ctx) {
20f7325489SJames Wright   PetscFunctionBeginUser;
21f7325489SJames Wright 
22f7325489SJames Wright   {  // Verify sizes
23f7325489SJames Wright     CeedSize x_size, y_size;
24f7325489SJames Wright     PetscInt X_size, Y_size;
25f7325489SJames Wright     CeedOperatorGetActiveVectorLengths(op_apply, &x_size, &y_size);
26f7325489SJames Wright     if (X_loc) {
27f7325489SJames Wright       PetscCall(VecGetLocalSize(X_loc, &X_size));
28f7325489SJames Wright       PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ,
29f7325489SJames Wright                  "X_loc (%" PetscInt_FMT ") not correct size for CeedOperator active input size (%" CeedSize_FMT ")", X_size, x_size);
30f7325489SJames Wright     }
31f7325489SJames Wright     if (Y_loc) {
32f7325489SJames Wright       PetscCall(VecGetLocalSize(Y_loc, &Y_size));
33f7325489SJames Wright       PetscCheck(Y_size == y_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ,
34f7325489SJames Wright                  "Y_loc (%" PetscInt_FMT ") not correct size for CeedOperator active output size (%" CeedSize_FMT ")", Y_size, y_size);
35f7325489SJames Wright     }
36f7325489SJames Wright   }
37f7325489SJames Wright 
38f7325489SJames Wright   PetscCall(PetscNew(op_apply_ctx));
39f7325489SJames Wright 
40f7325489SJames Wright   // Copy PETSc Objects
41f7325489SJames Wright   if (dm_x) PetscCall(PetscObjectReference((PetscObject)dm_x));
42f7325489SJames Wright   (*op_apply_ctx)->dm_x = dm_x;
43f7325489SJames Wright   if (dm_y) PetscCall(PetscObjectReference((PetscObject)dm_y));
44f7325489SJames Wright   (*op_apply_ctx)->dm_y = dm_y;
45f7325489SJames Wright 
46f7325489SJames Wright   if (X_loc) PetscCall(PetscObjectReference((PetscObject)X_loc));
47f7325489SJames Wright   (*op_apply_ctx)->X_loc = X_loc;
48f7325489SJames Wright   if (Y_loc) PetscCall(PetscObjectReference((PetscObject)Y_loc));
49f7325489SJames Wright   (*op_apply_ctx)->Y_loc = Y_loc;
50f7325489SJames Wright 
51f7325489SJames Wright   // Copy libCEED objects
52f7325489SJames Wright   if (x_ceed) CeedVectorReferenceCopy(x_ceed, &(*op_apply_ctx)->x_ceed);
53f7325489SJames Wright   if (y_ceed) CeedVectorReferenceCopy(y_ceed, &(*op_apply_ctx)->y_ceed);
54f7325489SJames Wright   CeedOperatorReferenceCopy(op_apply, &(*op_apply_ctx)->op);
55f7325489SJames Wright   CeedReferenceCopy(ceed, &(*op_apply_ctx)->ceed);
56f7325489SJames Wright 
57f7325489SJames Wright   PetscFunctionReturn(0);
58f7325489SJames Wright }
59f7325489SJames Wright 
60f7325489SJames Wright // -----------------------------------------------------------------------------
61f7325489SJames Wright // Destroy apply operator context data
62f7325489SJames Wright // -----------------------------------------------------------------------------
63f7325489SJames Wright PetscErrorCode OperatorApplyContextDestroy(OperatorApplyContext op_apply_ctx) {
64f7325489SJames Wright   PetscFunctionBeginUser;
65f7325489SJames Wright 
66f7325489SJames Wright   if (!op_apply_ctx) PetscFunctionReturn(0);
67f7325489SJames Wright 
68f7325489SJames Wright   // Destroy PETSc Objects
69f7325489SJames Wright   PetscCall(DMDestroy(&op_apply_ctx->dm_x));
70f7325489SJames Wright   PetscCall(DMDestroy(&op_apply_ctx->dm_y));
71f7325489SJames Wright   PetscCall(VecDestroy(&op_apply_ctx->X_loc));
72f7325489SJames Wright   PetscCall(VecDestroy(&op_apply_ctx->Y_loc));
73f7325489SJames Wright 
74f7325489SJames Wright   // Destroy libCEED Objects
75f7325489SJames Wright   CeedVectorDestroy(&op_apply_ctx->x_ceed);
76f7325489SJames Wright   CeedVectorDestroy(&op_apply_ctx->y_ceed);
77f7325489SJames Wright   CeedOperatorDestroy(&op_apply_ctx->op);
78f7325489SJames Wright   CeedDestroy(&op_apply_ctx->ceed);
79f7325489SJames Wright 
80f7325489SJames Wright   PetscCall(PetscFree(op_apply_ctx));
81f7325489SJames Wright 
82f7325489SJames Wright   PetscFunctionReturn(0);
83f7325489SJames Wright }
84f7325489SJames Wright 
85f7325489SJames Wright /**
86f7325489SJames Wright   @brief Transfer array from PETSc Vec to CeedVector
87f7325489SJames Wright 
88f7325489SJames Wright   @param[in]   X_petsc   PETSc Vec
89f7325489SJames Wright   @param[out]  mem_type  PETSc MemType
90f7325489SJames Wright   @param[out]  x_ceed    CeedVector
91f7325489SJames Wright 
92f7325489SJames Wright   @return An error code: 0 - success, otherwise - failure
93f7325489SJames Wright **/
94f7325489SJames Wright PetscErrorCode VecP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) {
95f7325489SJames Wright   PetscScalar *x;
96f7325489SJames Wright   PetscInt     X_size;
97f7325489SJames Wright   CeedSize     x_size;
98f7325489SJames Wright 
99f7325489SJames Wright   PetscFunctionBeginUser;
100f7325489SJames Wright   PetscCall(VecGetLocalSize(X_petsc, &X_size));
101f7325489SJames Wright   CeedVectorGetLength(x_ceed, &x_size);
102f7325489SJames 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",
103f7325489SJames Wright              X_size, x_size);
104f7325489SJames Wright 
105f7325489SJames Wright   PetscCall(VecGetArrayAndMemType(X_petsc, &x, mem_type));
106f7325489SJames Wright   CeedVectorSetArray(x_ceed, MemTypeP2C(*mem_type), CEED_USE_POINTER, x);
107f7325489SJames Wright 
108f7325489SJames Wright   PetscFunctionReturn(0);
109f7325489SJames Wright }
110f7325489SJames Wright 
111f7325489SJames Wright /**
112f7325489SJames Wright   @brief Transfer array from CeedVector to PETSc Vec
113f7325489SJames Wright 
114f7325489SJames Wright   @param[in]   x_ceed    CeedVector
115f7325489SJames Wright   @param[in]   mem_type  PETSc MemType
116f7325489SJames Wright   @param[out]  X_petsc   PETSc Vec
117f7325489SJames Wright 
118f7325489SJames Wright   @return An error code: 0 - success, otherwise - failure
119f7325489SJames Wright **/
120f7325489SJames Wright PetscErrorCode VecC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) {
121f7325489SJames Wright   PetscScalar *x;
122f7325489SJames Wright   PetscInt     X_size;
123f7325489SJames Wright   CeedSize     x_size;
124f7325489SJames Wright 
125f7325489SJames Wright   PetscFunctionBeginUser;
126f7325489SJames Wright   PetscCall(VecGetLocalSize(X_petsc, &X_size));
127f7325489SJames Wright   CeedVectorGetLength(x_ceed, &x_size);
128f7325489SJames 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",
129f7325489SJames Wright              X_size, x_size);
130f7325489SJames Wright 
131f7325489SJames Wright   CeedVectorTakeArray(x_ceed, MemTypeP2C(mem_type), &x);
132f7325489SJames Wright   PetscCall(VecRestoreArrayAndMemType(X_petsc, &x));
133f7325489SJames Wright 
134f7325489SJames Wright   PetscFunctionReturn(0);
135f7325489SJames Wright }
136f7325489SJames Wright 
137f7325489SJames Wright /**
138f7325489SJames Wright   @brief Transfer read-only array from PETSc Vec to CeedVector
139f7325489SJames Wright 
140f7325489SJames Wright   @param[in]   X_petsc   PETSc Vec
141f7325489SJames Wright   @param[out]  mem_type  PETSc MemType
142f7325489SJames Wright   @param[out]  x_ceed    CeedVector
143f7325489SJames Wright 
144f7325489SJames Wright   @return An error code: 0 - success, otherwise - failure
145f7325489SJames Wright **/
146f7325489SJames Wright PetscErrorCode VecReadP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) {
147f7325489SJames Wright   PetscScalar *x;
148f7325489SJames Wright   PetscInt     X_size;
149f7325489SJames Wright   CeedSize     x_size;
150f7325489SJames Wright 
151f7325489SJames Wright   PetscFunctionBeginUser;
152f7325489SJames Wright   PetscCall(VecGetLocalSize(X_petsc, &X_size));
153f7325489SJames Wright   CeedVectorGetLength(x_ceed, &x_size);
154f7325489SJames 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",
155f7325489SJames Wright              X_size, x_size);
156f7325489SJames Wright 
157f7325489SJames Wright   PetscCall(VecGetArrayReadAndMemType(X_petsc, (const PetscScalar **)&x, mem_type));
158f7325489SJames Wright   CeedVectorSetArray(x_ceed, MemTypeP2C(*mem_type), CEED_USE_POINTER, x);
159f7325489SJames Wright 
160f7325489SJames Wright   PetscFunctionReturn(0);
161f7325489SJames Wright }
162f7325489SJames Wright 
163f7325489SJames Wright /**
164f7325489SJames Wright   @brief Transfer read-only array from CeedVector to PETSc Vec
165f7325489SJames Wright 
166f7325489SJames Wright   @param[in]   x_ceed    CeedVector
167f7325489SJames Wright   @param[in]   mem_type  PETSc MemType
168f7325489SJames Wright   @param[out]  X_petsc   PETSc Vec
169f7325489SJames Wright 
170f7325489SJames Wright   @return An error code: 0 - success, otherwise - failure
171f7325489SJames Wright **/
172f7325489SJames Wright PetscErrorCode VecReadC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) {
173f7325489SJames Wright   PetscScalar *x;
174f7325489SJames Wright   PetscInt     X_size;
175f7325489SJames Wright   CeedSize     x_size;
176f7325489SJames Wright 
177f7325489SJames Wright   PetscFunctionBeginUser;
178f7325489SJames Wright   PetscCall(VecGetLocalSize(X_petsc, &X_size));
179f7325489SJames Wright   CeedVectorGetLength(x_ceed, &x_size);
180f7325489SJames 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",
181f7325489SJames Wright              X_size, x_size);
182f7325489SJames Wright 
183f7325489SJames Wright   CeedVectorTakeArray(x_ceed, MemTypeP2C(mem_type), &x);
184f7325489SJames Wright   PetscCall(VecRestoreArrayReadAndMemType(X_petsc, (const PetscScalar **)&x));
185f7325489SJames Wright 
186f7325489SJames Wright   PetscFunctionReturn(0);
187f7325489SJames Wright }
188f7325489SJames Wright 
189f7325489SJames Wright /**
190f7325489SJames Wright   @brief Copy PETSc Vec data into CeedVector
191f7325489SJames Wright 
192f7325489SJames Wright   @param[in]   X_petsc PETSc Vec
193f7325489SJames Wright   @param[out]  x_ceed  CeedVector
194f7325489SJames Wright 
195f7325489SJames Wright   @return An error code: 0 - success, otherwise - failure
196f7325489SJames Wright **/
197f7325489SJames Wright PetscErrorCode VecCopyP2C(Vec X_petsc, CeedVector x_ceed) {
198f7325489SJames Wright   PetscScalar *x;
199f7325489SJames Wright   PetscMemType mem_type;
200f7325489SJames Wright   PetscInt     X_size;
201f7325489SJames Wright   CeedSize     x_size;
202f7325489SJames Wright 
203f7325489SJames Wright   PetscFunctionBeginUser;
204f7325489SJames Wright   PetscCall(VecGetLocalSize(X_petsc, &X_size));
205f7325489SJames Wright   CeedVectorGetLength(x_ceed, &x_size);
206f7325489SJames 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",
207f7325489SJames Wright              X_size, x_size);
208f7325489SJames Wright 
209f7325489SJames Wright   PetscCall(VecGetArrayReadAndMemType(X_petsc, (const PetscScalar **)&x, &mem_type));
210f7325489SJames Wright   CeedVectorSetArray(x_ceed, MemTypeP2C(mem_type), CEED_COPY_VALUES, x);
211f7325489SJames Wright   PetscCall(VecRestoreArrayReadAndMemType(X_petsc, (const PetscScalar **)&x));
212f7325489SJames Wright 
213f7325489SJames Wright   PetscFunctionReturn(0);
214f7325489SJames Wright }
215f7325489SJames Wright 
216*6cbc221eSJames Wright //@brief Return VecType for the given DM
217*6cbc221eSJames Wright VecType DMReturnVecType(DM dm) {
218*6cbc221eSJames Wright   VecType vec_type;
219*6cbc221eSJames Wright   DMGetVecType(dm, &vec_type);
220*6cbc221eSJames Wright   return vec_type;
221*6cbc221eSJames Wright }
222*6cbc221eSJames Wright 
223*6cbc221eSJames Wright /**
224*6cbc221eSJames Wright  * @brief Create local PETSc Vecs for CeedOperator's active input/outputs
225*6cbc221eSJames Wright  *
226*6cbc221eSJames Wright  * This is primarily used for when the active input/ouput vector does not correspond to a `DM` object, and thus `DMCreateLocalVector` or
227*6cbc221eSJames Wright  * `DMGetLocalVector` are not applicable.
228*6cbc221eSJames Wright  * For example, if statitics are being store at quadrature points, a `DM`-created `Vec` will not have the
229*6cbc221eSJames Wright  * correct size.
230*6cbc221eSJames Wright  *
231*6cbc221eSJames Wright  * @param[in]  dm     DM overwhich the Vecs would be used
232*6cbc221eSJames Wright  * @param[in]  op     Operator to make the Vecs for
233*6cbc221eSJames Wright  * @param[out] input  Vec for CeedOperator active input
234*6cbc221eSJames Wright  * @param[out] output Vec for CeedOperator active output
235*6cbc221eSJames Wright  */
236*6cbc221eSJames Wright PetscErrorCode CeedOperatorCreateLocalVecs(CeedOperator op, VecType vec_type, MPI_Comm comm, Vec *input, Vec *output) {
237*6cbc221eSJames Wright   CeedSize input_size, output_size;
238*6cbc221eSJames Wright 
239*6cbc221eSJames Wright   PetscFunctionBeginUser;
240*6cbc221eSJames Wright   CeedOperatorGetActiveVectorLengths(op, &input_size, &output_size);
241*6cbc221eSJames Wright   if (input) {
242*6cbc221eSJames Wright     PetscCall(VecCreate(comm, input));
243*6cbc221eSJames Wright     PetscCall(VecSetType(*input, vec_type));
244*6cbc221eSJames Wright     PetscCall(VecSetSizes(*input, input_size, input_size));
245*6cbc221eSJames Wright   }
246*6cbc221eSJames Wright   if (output) {
247*6cbc221eSJames Wright     PetscCall(VecCreate(comm, output));
248*6cbc221eSJames Wright     PetscCall(VecSetType(*output, vec_type));
249*6cbc221eSJames Wright     PetscCall(VecSetSizes(*output, output_size, output_size));
250*6cbc221eSJames Wright   }
251*6cbc221eSJames Wright 
252*6cbc221eSJames Wright   PetscFunctionReturn(0);
253*6cbc221eSJames Wright }
254*6cbc221eSJames Wright 
255f7325489SJames Wright /**
256f7325489SJames Wright  * @brief Apply FEM Operator defined by `OperatorApplyContext` to various input and output vectors
257f7325489SJames Wright  *
258f7325489SJames Wright  * @param X             Input global `Vec`, maybe `NULL`
259f7325489SJames Wright  * @param X_loc         Input local `Vec`, maybe `NULL`
260f7325489SJames Wright  * @param x_ceed        Input `CeedVector`, maybe `CEED_VECTOR_NONE`
261f7325489SJames Wright  * @param y_ceed        Output `CeedVector`, maybe `CEED_VECTOR_NONE`
262f7325489SJames Wright  * @param Y_loc         Output local `Vec`, maybe `NULL`
263f7325489SJames Wright  * @param Y             Output global `Vec`, maybe `NULL`
264f7325489SJames Wright  * @param ctx           Context for the operator apply
265f7325489SJames Wright  * @param use_apply_add Whether to use `CeedOperatorApply` or `CeedOperatorApplyAdd`
266f7325489SJames Wright  */
267f7325489SJames Wright PetscErrorCode ApplyCeedOperator_Core(Vec X, Vec X_loc, CeedVector x_ceed, CeedVector y_ceed, Vec Y_loc, Vec Y, OperatorApplyContext ctx,
268f7325489SJames Wright                                       bool use_apply_add) {
269f7325489SJames Wright   PetscMemType x_mem_type, y_mem_type;
270f7325489SJames Wright 
271f7325489SJames Wright   PetscFunctionBeginUser;
272f7325489SJames Wright   if (X) PetscCall(DMGlobalToLocal(ctx->dm_x, X, INSERT_VALUES, X_loc));
273f7325489SJames Wright   if (X_loc) PetscCall(VecReadP2C(X_loc, &x_mem_type, x_ceed));
274f7325489SJames Wright 
275f7325489SJames Wright   if (Y_loc) PetscCall(VecP2C(Y_loc, &y_mem_type, y_ceed));
276f7325489SJames Wright 
277f7325489SJames Wright   if (use_apply_add) CeedOperatorApplyAdd(ctx->op, x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE);
278f7325489SJames Wright   else CeedOperatorApply(ctx->op, x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE);
279f7325489SJames Wright 
280f7325489SJames Wright   if (X_loc) PetscCall(VecReadC2P(ctx->x_ceed, x_mem_type, X_loc));
281f7325489SJames Wright 
282f7325489SJames Wright   if (Y_loc) PetscCall(VecC2P(ctx->y_ceed, y_mem_type, Y_loc));
283f7325489SJames Wright   if (Y) PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, Y));
284f7325489SJames Wright 
285f7325489SJames Wright   PetscFunctionReturn(0);
286f7325489SJames Wright };
287f7325489SJames Wright 
288f7325489SJames Wright PetscErrorCode ApplyCeedOperatorGlobalToGlobal(Vec X, Vec Y, OperatorApplyContext ctx) {
289f7325489SJames Wright   Vec X_loc = ctx->X_loc, Y_loc = ctx->Y_loc;
290f7325489SJames Wright 
291f7325489SJames Wright   PetscFunctionBeginUser;
292f7325489SJames Wright   PetscCall(VecZeroEntries(Y));
293f7325489SJames Wright 
294f7325489SJames Wright   // Get local vectors (if needed)
295f7325489SJames Wright   if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc));
296f7325489SJames Wright   if (!ctx->Y_loc) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc));
297f7325489SJames Wright 
298f7325489SJames Wright   PetscCall(ApplyCeedOperator_Core(X, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, Y, ctx, false));
299f7325489SJames Wright 
300f7325489SJames Wright   // Restore local vector (if needed)
301f7325489SJames Wright   if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc));
302f7325489SJames Wright   if (!ctx->Y_loc) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc));
303f7325489SJames Wright 
304f7325489SJames Wright   PetscFunctionReturn(0);
305f7325489SJames Wright }
306f7325489SJames Wright 
307f7325489SJames Wright PetscErrorCode ApplyCeedOperatorLocalToGlobal(Vec X_loc, Vec Y, OperatorApplyContext ctx) {
308f7325489SJames Wright   Vec Y_loc = ctx->Y_loc;
309f7325489SJames Wright 
310f7325489SJames Wright   PetscFunctionBeginUser;
311f7325489SJames Wright   PetscCall(VecZeroEntries(Y));
312f7325489SJames Wright 
313f7325489SJames Wright   // Get local vectors (if needed)
314f7325489SJames Wright   if (!ctx->Y_loc) PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc));
315f7325489SJames Wright 
316f7325489SJames Wright   PetscCall(ApplyCeedOperator_Core(NULL, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, Y, ctx, false));
317f7325489SJames Wright 
318f7325489SJames Wright   // Restore local vectors (if needed)
319f7325489SJames Wright   if (!ctx->Y_loc) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc));
320f7325489SJames Wright 
321f7325489SJames Wright   PetscFunctionReturn(0);
322f7325489SJames Wright }
323f7325489SJames Wright 
324f7325489SJames Wright PetscErrorCode ApplyCeedOperatorGlobalToLocal(Vec X, Vec Y_loc, OperatorApplyContext ctx) {
325f7325489SJames Wright   Vec X_loc = ctx->X_loc;
326f7325489SJames Wright 
327f7325489SJames Wright   PetscFunctionBeginUser;
328f7325489SJames Wright   // Get local vectors (if needed)
329f7325489SJames Wright   if (!ctx->X_loc) PetscCall(DMGetLocalVector(ctx->dm_x, &X_loc));
330f7325489SJames Wright 
331f7325489SJames Wright   PetscCall(ApplyCeedOperator_Core(X, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, NULL, ctx, false));
332f7325489SJames Wright 
333f7325489SJames Wright   // Restore local vector (if needed)
334f7325489SJames Wright   if (!ctx->X_loc) PetscCall(DMRestoreLocalVector(ctx->dm_x, &X_loc));
335f7325489SJames Wright 
336f7325489SJames Wright   PetscFunctionReturn(0);
337f7325489SJames Wright }
338f7325489SJames Wright 
339f7325489SJames Wright PetscErrorCode ApplyAddCeedOperatorLocalToLocal(Vec X_loc, Vec Y_loc, OperatorApplyContext ctx) {
340f7325489SJames Wright   PetscFunctionBeginUser;
341f7325489SJames Wright   PetscCall(ApplyCeedOperator_Core(NULL, X_loc, ctx->x_ceed, ctx->y_ceed, Y_loc, NULL, ctx, true));
342f7325489SJames Wright   PetscFunctionReturn(0);
343f7325489SJames Wright }
344f7325489SJames Wright 
345f7325489SJames Wright // -----------------------------------------------------------------------------
346f7325489SJames Wright // Wraps the libCEED operator for a MatShell
347f7325489SJames Wright // -----------------------------------------------------------------------------
348f7325489SJames Wright PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) {
349f7325489SJames Wright   OperatorApplyContext ctx;
350f7325489SJames Wright   PetscFunctionBeginUser;
351f7325489SJames Wright 
352f7325489SJames Wright   PetscCall(MatShellGetContext(A, &ctx));
353f7325489SJames Wright   PetscCall(ApplyCeedOperatorGlobalToGlobal(X, Y, ctx));
354f7325489SJames Wright 
355f7325489SJames Wright   PetscFunctionReturn(0);
356f7325489SJames Wright };
357f7325489SJames Wright 
358f7325489SJames Wright // -----------------------------------------------------------------------------
359f7325489SJames Wright // Returns the computed diagonal of the operator
360f7325489SJames Wright // -----------------------------------------------------------------------------
361f7325489SJames Wright PetscErrorCode MatGetDiag_Ceed(Mat A, Vec D) {
362f7325489SJames Wright   OperatorApplyContext ctx;
363f7325489SJames Wright   Vec                  Y_loc;
364f7325489SJames Wright   PetscMemType         mem_type;
365f7325489SJames Wright   PetscFunctionBeginUser;
366f7325489SJames Wright 
367f7325489SJames Wright   PetscCall(MatShellGetContext(A, &ctx));
368f7325489SJames Wright   if (ctx->Y_loc) Y_loc = ctx->Y_loc;
369f7325489SJames Wright   else PetscCall(DMGetLocalVector(ctx->dm_y, &Y_loc));
370f7325489SJames Wright 
371f7325489SJames Wright   // -- Place PETSc vector in libCEED vector
372f7325489SJames Wright   PetscCall(VecP2C(Y_loc, &mem_type, ctx->y_ceed));
373f7325489SJames Wright 
374f7325489SJames Wright   // -- Compute Diagonal
375f7325489SJames Wright   CeedOperatorLinearAssembleDiagonal(ctx->op, ctx->y_ceed, CEED_REQUEST_IMMEDIATE);
376f7325489SJames Wright 
377f7325489SJames Wright   // -- Local-to-Global
378f7325489SJames Wright   PetscCall(VecC2P(ctx->y_ceed, mem_type, Y_loc));
379f7325489SJames Wright   PetscCall(VecZeroEntries(D));
380f7325489SJames Wright   PetscCall(DMLocalToGlobal(ctx->dm_y, Y_loc, ADD_VALUES, D));
381f7325489SJames Wright 
382f7325489SJames Wright   if (!ctx->Y_loc) PetscCall(DMRestoreLocalVector(ctx->dm_y, &Y_loc));
383f7325489SJames Wright   PetscFunctionReturn(0);
384f7325489SJames Wright };
385f7325489SJames Wright 
386f7325489SJames Wright // -----------------------------------------------------------------------------
387