xref: /petsc/src/dm/interface/dmceed.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1f918ec44SMatthew G. Knepley #include <petsc/private/dmimpl.h> /*I      "petscdm.h"          I*/
2d2b2dc1eSMatthew G. Knepley #include <petscdmceed.h>
3f918ec44SMatthew G. Knepley 
4f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5d2b2dc1eSMatthew G. Knepley   #include <petsc/private/dmpleximpl.h>
6d2b2dc1eSMatthew G. Knepley   #include <petscdmplexceed.h>
7d2b2dc1eSMatthew G. Knepley   #include <petscfeceed.h>
8f918ec44SMatthew G. Knepley 
9f918ec44SMatthew G. Knepley /*@C
1020f4b53cSBarry Smith   DMGetCeed - Get the LibCEED context associated with this `DM`
11f918ec44SMatthew G. Knepley 
1220f4b53cSBarry Smith   Not Collective
13f918ec44SMatthew G. Knepley 
14f918ec44SMatthew G. Knepley   Input Parameter:
1520f4b53cSBarry Smith . DM   - The `DM`
16f918ec44SMatthew G. Knepley 
17f918ec44SMatthew G. Knepley   Output Parameter:
18f918ec44SMatthew G. Knepley . ceed - The LibCEED context
19f918ec44SMatthew G. Knepley 
20f918ec44SMatthew G. Knepley   Level: intermediate
21f918ec44SMatthew G. Knepley 
2220f4b53cSBarry Smith .seealso: `DM`, `DMCreate()`
23f918ec44SMatthew G. Knepley @*/
DMGetCeed(DM dm,Ceed * ceed)24d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCeed(DM dm, Ceed *ceed)
25d71ae5a4SJacob Faibussowitsch {
26f918ec44SMatthew G. Knepley   PetscFunctionBegin;
27f918ec44SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
284f572ea9SToby Isaac   PetscAssertPointer(ceed, 2);
29f918ec44SMatthew G. Knepley   if (!dm->ceed) {
30f918ec44SMatthew G. Knepley     char        ceedresource[PETSC_MAX_PATH_LEN]; /* libCEED resource specifier */
31f918ec44SMatthew G. Knepley     const char *prefix;
32f918ec44SMatthew G. Knepley 
33c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(ceedresource, "/cpu/self", sizeof(ceedresource)));
349566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
359566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(NULL, prefix, "-dm_ceed", ceedresource, sizeof(ceedresource), NULL));
369566063dSJacob Faibussowitsch     PetscCallCEED(CeedInit(ceedresource, &dm->ceed));
37f918ec44SMatthew G. Knepley   }
38f918ec44SMatthew G. Knepley   *ceed = dm->ceed;
393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40f918ec44SMatthew G. Knepley }
41f918ec44SMatthew G. Knepley 
PetscMemType2Ceed(PetscMemType mem_type)42d2b2dc1eSMatthew G. Knepley static CeedMemType PetscMemType2Ceed(PetscMemType mem_type)
43d2b2dc1eSMatthew G. Knepley {
447ce467fcSMatthew G. Knepley   return PetscMemTypeDevice(mem_type) ? CEED_MEM_DEVICE : CEED_MEM_HOST;
457ce467fcSMatthew G. Knepley }
467ce467fcSMatthew G. Knepley 
VecGetCeedVector(Vec X,Ceed ceed,CeedVector * cx)477ce467fcSMatthew G. Knepley PetscErrorCode VecGetCeedVector(Vec X, Ceed ceed, CeedVector *cx)
487ce467fcSMatthew G. Knepley {
497ce467fcSMatthew G. Knepley   PetscMemType memtype;
507ce467fcSMatthew G. Knepley   PetscScalar *x;
517ce467fcSMatthew G. Knepley   PetscInt     n;
527ce467fcSMatthew G. Knepley 
537ce467fcSMatthew G. Knepley   PetscFunctionBegin;
547ce467fcSMatthew G. Knepley   PetscCall(VecGetLocalSize(X, &n));
557ce467fcSMatthew G. Knepley   PetscCall(VecGetArrayAndMemType(X, &x, &memtype));
567ce467fcSMatthew G. Knepley   PetscCallCEED(CeedVectorCreate(ceed, n, cx));
577ce467fcSMatthew G. Knepley   PetscCallCEED(CeedVectorSetArray(*cx, PetscMemType2Ceed(memtype), CEED_USE_POINTER, x));
58d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
597ce467fcSMatthew G. Knepley }
607ce467fcSMatthew G. Knepley 
VecRestoreCeedVector(Vec X,CeedVector * cx)617ce467fcSMatthew G. Knepley PetscErrorCode VecRestoreCeedVector(Vec X, CeedVector *cx)
627ce467fcSMatthew G. Knepley {
637ce467fcSMatthew G. Knepley   PetscFunctionBegin;
647ce467fcSMatthew G. Knepley   PetscCall(VecRestoreArrayAndMemType(X, NULL));
657ce467fcSMatthew G. Knepley   PetscCallCEED(CeedVectorDestroy(cx));
66d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
677ce467fcSMatthew G. Knepley }
687ce467fcSMatthew G. Knepley 
VecGetCeedVectorRead(Vec X,Ceed ceed,CeedVector * cx)697ce467fcSMatthew G. Knepley PetscErrorCode VecGetCeedVectorRead(Vec X, Ceed ceed, CeedVector *cx)
707ce467fcSMatthew G. Knepley {
717ce467fcSMatthew G. Knepley   PetscMemType       memtype;
727ce467fcSMatthew G. Knepley   const PetscScalar *x;
737ce467fcSMatthew G. Knepley   PetscInt           n;
744d86920dSPierre Jolivet 
757ce467fcSMatthew G. Knepley   PetscFunctionBegin;
767ce467fcSMatthew G. Knepley   PetscCall(VecGetLocalSize(X, &n));
777ce467fcSMatthew G. Knepley   PetscCall(VecGetArrayReadAndMemType(X, &x, &memtype));
787ce467fcSMatthew G. Knepley   PetscCallCEED(CeedVectorCreate(ceed, n, cx));
797ce467fcSMatthew G. Knepley   PetscCallCEED(CeedVectorSetArray(*cx, PetscMemType2Ceed(memtype), CEED_USE_POINTER, (PetscScalar *)x));
80d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
817ce467fcSMatthew G. Knepley }
827ce467fcSMatthew G. Knepley 
VecRestoreCeedVectorRead(Vec X,CeedVector * cx)837ce467fcSMatthew G. Knepley PetscErrorCode VecRestoreCeedVectorRead(Vec X, CeedVector *cx)
847ce467fcSMatthew G. Knepley {
857ce467fcSMatthew G. Knepley   PetscFunctionBegin;
867ce467fcSMatthew G. Knepley   PetscCall(VecRestoreArrayReadAndMemType(X, NULL));
877ce467fcSMatthew G. Knepley   PetscCallCEED(CeedVectorDestroy(cx));
88d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
89d2b2dc1eSMatthew G. Knepley }
90d2b2dc1eSMatthew G. Knepley 
Geometry2D(PetscCtx ctx,const CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)91*2a8381b2SBarry Smith CEED_QFUNCTION(Geometry2D)(PetscCtx ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out)
92d2b2dc1eSMatthew G. Knepley {
93d2b2dc1eSMatthew G. Knepley   const CeedScalar *x = in[0], *Jac = in[1], *w = in[2];
94d2b2dc1eSMatthew G. Knepley   CeedScalar       *qdata = out[0];
95d2b2dc1eSMatthew G. Knepley 
96d2b2dc1eSMatthew G. Knepley   CeedPragmaSIMD for (CeedInt i = 0; i < Q; ++i)
97d2b2dc1eSMatthew G. Knepley   {
98d2b2dc1eSMatthew G. Knepley     const CeedScalar J[2][2] = {
99d2b2dc1eSMatthew G. Knepley       {Jac[i + Q * 0], Jac[i + Q * 2]},
100d2b2dc1eSMatthew G. Knepley       {Jac[i + Q * 1], Jac[i + Q * 3]}
101d2b2dc1eSMatthew G. Knepley     };
102d2b2dc1eSMatthew G. Knepley     const CeedScalar det = J[0][0] * J[1][1] - J[0][1] * J[1][0];
103d2b2dc1eSMatthew G. Knepley 
104d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 0] = det * w[i];
105d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 1] = x[i + Q * 0];
106d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 2] = x[i + Q * 1];
107d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 3] = J[1][1] / det;
108d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 4] = -J[1][0] / det;
109d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 5] = -J[0][1] / det;
110d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 6] = J[0][0] / det;
111d2b2dc1eSMatthew G. Knepley   }
112d2b2dc1eSMatthew G. Knepley   return CEED_ERROR_SUCCESS;
113d2b2dc1eSMatthew G. Knepley }
114d2b2dc1eSMatthew G. Knepley 
Geometry3D(PetscCtx ctx,const CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)115*2a8381b2SBarry Smith CEED_QFUNCTION(Geometry3D)(PetscCtx ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out)
116d2b2dc1eSMatthew G. Knepley {
117d2b2dc1eSMatthew G. Knepley   const CeedScalar *Jac = in[1], *w = in[2];
118d2b2dc1eSMatthew G. Knepley   CeedScalar       *qdata = out[0];
119d2b2dc1eSMatthew G. Knepley 
120d2b2dc1eSMatthew G. Knepley   CeedPragmaSIMD for (CeedInt i = 0; i < Q; ++i)
121d2b2dc1eSMatthew G. Knepley   {
122d2b2dc1eSMatthew G. Knepley     const CeedScalar J[3][3] = {
123d2b2dc1eSMatthew G. Knepley       {Jac[i + Q * 0], Jac[i + Q * 3], Jac[i + Q * 6]},
124d2b2dc1eSMatthew G. Knepley       {Jac[i + Q * 1], Jac[i + Q * 4], Jac[i + Q * 7]},
125d2b2dc1eSMatthew G. Knepley       {Jac[i + Q * 2], Jac[i + Q * 5], Jac[i + Q * 8]}
126d2b2dc1eSMatthew G. Knepley     };
127d2b2dc1eSMatthew G. Knepley     const CeedScalar det = J[0][0] * (J[1][1] * J[2][2] - J[1][2] * J[2][1]) + J[0][1] * (J[1][2] * J[2][0] - J[1][0] * J[2][2]) + J[0][2] * (J[1][0] * J[2][1] - J[1][1] * J[2][0]);
128d2b2dc1eSMatthew G. Knepley 
129d2b2dc1eSMatthew G. Knepley     qdata[i + Q * 0] = det * w[i]; /* det J * weight */
130d2b2dc1eSMatthew G. Knepley   }
131d2b2dc1eSMatthew G. Knepley   return CEED_ERROR_SUCCESS;
132d2b2dc1eSMatthew G. Knepley }
133d2b2dc1eSMatthew G. Knepley 
DMCeedCreateGeometry(DM dm,IS cellIS,PetscInt * Nqdata,CeedElemRestriction * erq,CeedVector * qd,DMCeed * soldata)134d2b2dc1eSMatthew G. Knepley static PetscErrorCode DMCeedCreateGeometry(DM dm, IS cellIS, PetscInt *Nqdata, CeedElemRestriction *erq, CeedVector *qd, DMCeed *soldata)
135d2b2dc1eSMatthew G. Knepley {
136d2b2dc1eSMatthew G. Knepley   Ceed              ceed;
137d2b2dc1eSMatthew G. Knepley   DMCeed            sd;
138d2b2dc1eSMatthew G. Knepley   PetscDS           ds;
139d2b2dc1eSMatthew G. Knepley   PetscFE           fe;
140d2b2dc1eSMatthew G. Knepley   CeedQFunctionUser geom     = NULL;
141d2b2dc1eSMatthew G. Knepley   const char       *geomName = NULL;
142d2b2dc1eSMatthew G. Knepley   const PetscInt   *cells;
14385f1dce8SJed Brown   PetscInt          dim, cdim, cStart, cEnd, Ncell;
14485f1dce8SJed Brown   CeedInt           Nq;
145d2b2dc1eSMatthew G. Knepley 
146d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
147d2b2dc1eSMatthew G. Knepley   PetscCall(PetscCalloc1(1, &sd));
148d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
149d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &cdim));
150d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetCeed(dm, &ceed));
151d2b2dc1eSMatthew G. Knepley   PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
152d2b2dc1eSMatthew G. Knepley   Ncell = cEnd - cStart;
153d2b2dc1eSMatthew G. Knepley 
154d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &ds, NULL));
155d2b2dc1eSMatthew G. Knepley   PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe));
156d2b2dc1eSMatthew G. Knepley   PetscCall(PetscFEGetCeedBasis(fe, &sd->basis));
157d2b2dc1eSMatthew G. Knepley   PetscCall(CeedBasisGetNumQuadraturePoints(sd->basis, &Nq));
158d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetCeedRestriction(dm, NULL, 0, 0, 0, &sd->er));
159d2b2dc1eSMatthew G. Knepley 
1605962854dSMatthew G. Knepley   *Nqdata = 1 + cdim + cdim * dim; // |J| * w_q, x, J^{-1}
161d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedElemRestrictionCreateStrided(ceed, Ncell, Nq, *Nqdata, Ncell * Nq * (*Nqdata), CEED_STRIDES_BACKEND, erq));
162d2b2dc1eSMatthew G. Knepley 
163d2b2dc1eSMatthew G. Knepley   switch (dim) {
164d2b2dc1eSMatthew G. Knepley   case 2:
165d2b2dc1eSMatthew G. Knepley     geom     = Geometry2D;
166d2b2dc1eSMatthew G. Knepley     geomName = Geometry2D_loc;
167d2b2dc1eSMatthew G. Knepley     break;
168d2b2dc1eSMatthew G. Knepley   case 3:
169d2b2dc1eSMatthew G. Knepley     geom     = Geometry3D;
170d2b2dc1eSMatthew G. Knepley     geomName = Geometry3D_loc;
171d2b2dc1eSMatthew G. Knepley     break;
172d2b2dc1eSMatthew G. Knepley   }
173d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionCreateInterior(ceed, 1, geom, geomName, &sd->qf));
174d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "x", cdim, CEED_EVAL_INTERP));
175d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "dx", cdim * dim, CEED_EVAL_GRAD));
176d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "weight", 1, CEED_EVAL_WEIGHT));
177d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddOutput(sd->qf, "qdata", *Nqdata, CEED_EVAL_NONE));
178d2b2dc1eSMatthew G. Knepley 
179d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorCreate(ceed, sd->qf, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &sd->op));
180d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorSetField(sd->op, "x", sd->er, sd->basis, CEED_VECTOR_ACTIVE));
181d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorSetField(sd->op, "dx", sd->er, sd->basis, CEED_VECTOR_ACTIVE));
182d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorSetField(sd->op, "weight", CEED_ELEMRESTRICTION_NONE, sd->basis, CEED_VECTOR_NONE));
18310ae67c6SJeremy L Thompson   PetscCallCEED(CeedOperatorSetField(sd->op, "qdata", *erq, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
184d2b2dc1eSMatthew G. Knepley 
185d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedElemRestrictionCreateVector(*erq, qd, NULL));
186d2b2dc1eSMatthew G. Knepley   *soldata = sd;
187d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
188d2b2dc1eSMatthew G. Knepley }
189d2b2dc1eSMatthew G. Knepley 
DMRefineHook_Ceed(DM coarse,DM fine,PetscCtx ctx)190*2a8381b2SBarry Smith PetscErrorCode DMRefineHook_Ceed(DM coarse, DM fine, PetscCtx ctx)
191d2b2dc1eSMatthew G. Knepley {
192d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
193d2b2dc1eSMatthew G. Knepley   if (coarse->dmceed) PetscCall(DMCeedCreate(fine, coarse->dmceed->geom ? PETSC_TRUE : PETSC_FALSE, coarse->dmceed->func, coarse->dmceed->funcSource));
194d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
195d2b2dc1eSMatthew G. Knepley }
196d2b2dc1eSMatthew G. Knepley 
DMCeedCreate_Internal(DM dm,IS cellIS,PetscBool createGeometry,CeedQFunctionUser func,const char * func_source,DMCeed * soldata)197d2b2dc1eSMatthew G. Knepley PetscErrorCode DMCeedCreate_Internal(DM dm, IS cellIS, PetscBool createGeometry, CeedQFunctionUser func, const char *func_source, DMCeed *soldata)
198d2b2dc1eSMatthew G. Knepley {
199d2b2dc1eSMatthew G. Knepley   PetscDS  ds;
200d2b2dc1eSMatthew G. Knepley   PetscFE  fe;
201d2b2dc1eSMatthew G. Knepley   DMCeed   sd;
202d2b2dc1eSMatthew G. Knepley   Ceed     ceed;
20385f1dce8SJed Brown   PetscInt dim, Nc, Nqdata = 0;
20485f1dce8SJed Brown   CeedInt  Nq;
205d2b2dc1eSMatthew G. Knepley 
206d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
207d2b2dc1eSMatthew G. Knepley   PetscCall(PetscCalloc1(1, &sd));
208d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
209d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetCeed(dm, &ceed));
210d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetDS(dm, &ds));
211d2b2dc1eSMatthew G. Knepley   PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe));
212d2b2dc1eSMatthew G. Knepley   PetscCall(PetscFEGetCeedBasis(fe, &sd->basis));
213d2b2dc1eSMatthew G. Knepley   PetscCall(PetscFEGetNumComponents(fe, &Nc));
214d2b2dc1eSMatthew G. Knepley   PetscCall(CeedBasisGetNumQuadraturePoints(sd->basis, &Nq));
215d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetCeedRestriction(dm, NULL, 0, 0, 0, &sd->er));
216d2b2dc1eSMatthew G. Knepley 
217d2b2dc1eSMatthew G. Knepley   if (createGeometry) {
218d2b2dc1eSMatthew G. Knepley     DM cdm;
219d2b2dc1eSMatthew G. Knepley 
220d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
221d2b2dc1eSMatthew G. Knepley     PetscCall(DMCeedCreateGeometry(cdm, cellIS, &Nqdata, &sd->erq, &sd->qd, &sd->geom));
222d2b2dc1eSMatthew G. Knepley   }
223d2b2dc1eSMatthew G. Knepley 
224d2b2dc1eSMatthew G. Knepley   if (sd->geom) {
22585f1dce8SJed Brown     PetscInt cdim;
22685f1dce8SJed Brown     CeedInt  Nqx;
227d2b2dc1eSMatthew G. Knepley 
228d2b2dc1eSMatthew G. Knepley     PetscCallCEED(CeedBasisGetNumQuadraturePoints(sd->geom->basis, &Nqx));
22985f1dce8SJed Brown     PetscCheck(Nqx == Nq, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Number of qpoints for solution %" CeedInt_FMT " != %" CeedInt_FMT " Number of qpoints for coordinates", Nq, Nqx);
230d2b2dc1eSMatthew G. Knepley     /* TODO Remove this limitation */
231d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &cdim));
232d2b2dc1eSMatthew G. Knepley     PetscCheck(dim == cdim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Topological dimension %" PetscInt_FMT " != %" PetscInt_FMT " embedding dimension", dim, cdim);
233d2b2dc1eSMatthew G. Knepley   }
234d2b2dc1eSMatthew G. Knepley 
235d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionCreateInterior(ceed, 1, func, func_source, &sd->qf));
236d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "u", Nc, CEED_EVAL_INTERP));
237d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "du", Nc * dim, CEED_EVAL_GRAD));
238d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "qdata", Nqdata, CEED_EVAL_NONE));
239d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddOutput(sd->qf, "v", Nc, CEED_EVAL_INTERP));
240d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddOutput(sd->qf, "dv", Nc * dim, CEED_EVAL_GRAD));
241d2b2dc1eSMatthew G. Knepley 
242d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorCreate(ceed, sd->qf, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &sd->op));
243d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorSetField(sd->op, "u", sd->er, sd->basis, CEED_VECTOR_ACTIVE));
244d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorSetField(sd->op, "du", sd->er, sd->basis, CEED_VECTOR_ACTIVE));
24510ae67c6SJeremy L Thompson   PetscCallCEED(CeedOperatorSetField(sd->op, "qdata", sd->erq, CEED_BASIS_NONE, sd->qd));
246d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorSetField(sd->op, "v", sd->er, sd->basis, CEED_VECTOR_ACTIVE));
247d2b2dc1eSMatthew G. Knepley   PetscCallCEED(CeedOperatorSetField(sd->op, "dv", sd->er, sd->basis, CEED_VECTOR_ACTIVE));
248d2b2dc1eSMatthew G. Knepley 
249d2b2dc1eSMatthew G. Knepley   // Handle refinement
250d2b2dc1eSMatthew G. Knepley   sd->func = func;
251d2b2dc1eSMatthew G. Knepley   PetscCall(PetscStrallocpy(func_source, &sd->funcSource));
252d2b2dc1eSMatthew G. Knepley   PetscCall(DMRefineHookAdd(dm, DMRefineHook_Ceed, NULL, NULL));
253d2b2dc1eSMatthew G. Knepley 
254d2b2dc1eSMatthew G. Knepley   *soldata = sd;
255d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
256d2b2dc1eSMatthew G. Knepley }
257d2b2dc1eSMatthew G. Knepley 
DMCeedCreate(DM dm,PetscBool createGeometry,CeedQFunctionUser func,const char * func_source)258d2b2dc1eSMatthew G. Knepley PetscErrorCode DMCeedCreate(DM dm, PetscBool createGeometry, CeedQFunctionUser func, const char *func_source)
259d2b2dc1eSMatthew G. Knepley {
260d2b2dc1eSMatthew G. Knepley   DM plex;
261d2b2dc1eSMatthew G. Knepley   IS cellIS;
262d2b2dc1eSMatthew G. Knepley 
263d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
264d2b2dc1eSMatthew G. Knepley   PetscCall(DMConvert(dm, DMPLEX, &plex));
265d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetAllCells_Internal(plex, &cellIS));
266d2b2dc1eSMatthew G. Knepley   #ifdef PETSC_HAVE_LIBCEED
267d2b2dc1eSMatthew G. Knepley   PetscCall(DMCeedCreate_Internal(dm, cellIS, createGeometry, func, func_source, &dm->dmceed));
268d2b2dc1eSMatthew G. Knepley   #endif
269d2b2dc1eSMatthew G. Knepley   PetscCall(ISDestroy(&cellIS));
270d2b2dc1eSMatthew G. Knepley   PetscCall(DMDestroy(&plex));
271d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2727ce467fcSMatthew G. Knepley }
2737ce467fcSMatthew G. Knepley 
DMCeedCreateGeometryFVM(DM dm,IS faceIS,PetscInt * Nqdata,CeedElemRestriction * erq,CeedVector * qd,DMCeed * soldata)2745962854dSMatthew G. Knepley static PetscErrorCode DMCeedCreateGeometryFVM(DM dm, IS faceIS, PetscInt *Nqdata, CeedElemRestriction *erq, CeedVector *qd, DMCeed *soldata)
2755962854dSMatthew G. Knepley {
2765962854dSMatthew G. Knepley   Ceed            ceed;
2775962854dSMatthew G. Knepley   DMCeed          sd;
2785962854dSMatthew G. Knepley   const PetscInt *faces;
279a2bd4c7eSAlbert Cowie   CeedInt         strides[3];
2805962854dSMatthew G. Knepley   PetscInt        dim, cdim, fStart, fEnd, Nface, Nq = 1;
2815962854dSMatthew G. Knepley 
2825962854dSMatthew G. Knepley   PetscFunctionBegin;
2835962854dSMatthew G. Knepley   PetscCall(PetscCalloc1(1, &sd));
2845962854dSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
2855962854dSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &cdim));
2865962854dSMatthew G. Knepley   PetscCall(DMGetCeed(dm, &ceed));
2875962854dSMatthew G. Knepley   PetscCall(ISGetPointRange(faceIS, &fStart, &fEnd, &faces));
2885962854dSMatthew G. Knepley   Nface = fEnd - fStart;
2895962854dSMatthew G. Knepley 
2905962854dSMatthew G. Knepley   *Nqdata    = cdim + 2; // face normal and support cell volumes
291a2bd4c7eSAlbert Cowie   strides[0] = 1;
292a2bd4c7eSAlbert Cowie   strides[1] = Nq;
293a2bd4c7eSAlbert Cowie   strides[2] = Nq * (*Nqdata);
294a2bd4c7eSAlbert Cowie   PetscCallCEED(CeedElemRestrictionCreateStrided(ceed, Nface, Nq, *Nqdata, Nface * Nq * (*Nqdata), strides, erq));
2955962854dSMatthew G. Knepley   PetscCallCEED(CeedElemRestrictionCreateVector(*erq, qd, NULL));
2965962854dSMatthew G. Knepley   *soldata = sd;
2975962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2985962854dSMatthew G. Knepley }
2995962854dSMatthew G. Knepley 
DMCeedCreateInfoFVM(DM dm,IS faceIS,PetscInt * Nqinfo,CeedElemRestriction * eri,CeedVector * qi,DMCeed * solinfo)300354b609cSMatthew G. Knepley static PetscErrorCode DMCeedCreateInfoFVM(DM dm, IS faceIS, PetscInt *Nqinfo, CeedElemRestriction *eri, CeedVector *qi, DMCeed *solinfo)
301354b609cSMatthew G. Knepley {
302354b609cSMatthew G. Knepley   Ceed            ceed;
303354b609cSMatthew G. Knepley   DMCeed          si;
304354b609cSMatthew G. Knepley   const PetscInt *faces;
305a2bd4c7eSAlbert Cowie   CeedInt         strides[3];
306354b609cSMatthew G. Knepley   PetscInt        dim, fStart, fEnd, Nface, Nq = 1;
307354b609cSMatthew G. Knepley 
308354b609cSMatthew G. Knepley   PetscFunctionBegin;
309354b609cSMatthew G. Knepley   PetscCall(PetscCalloc1(1, &si));
310354b609cSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
311354b609cSMatthew G. Knepley   PetscCall(DMGetCeed(dm, &ceed));
312354b609cSMatthew G. Knepley   PetscCall(ISGetPointRange(faceIS, &fStart, &fEnd, &faces));
313354b609cSMatthew G. Knepley   Nface = fEnd - fStart;
314354b609cSMatthew G. Knepley 
315354b609cSMatthew G. Knepley   *Nqinfo    = 3; // face number and support cell numbers
316a2bd4c7eSAlbert Cowie   strides[0] = 1;
317a2bd4c7eSAlbert Cowie   strides[1] = Nq;
318a2bd4c7eSAlbert Cowie   strides[2] = Nq * (*Nqinfo);
319a2bd4c7eSAlbert Cowie   PetscCallCEED(CeedElemRestrictionCreateStrided(ceed, Nface, Nq, *Nqinfo, Nface * Nq * (*Nqinfo), strides, eri));
320354b609cSMatthew G. Knepley   PetscCallCEED(CeedElemRestrictionCreateVector(*eri, qi, NULL));
321354b609cSMatthew G. Knepley   *solinfo = si;
322354b609cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
323354b609cSMatthew G. Knepley }
324354b609cSMatthew G. Knepley 
DMCeedCreateFVM_Internal(DM dm,IS faceIS,PetscBool createGeometry,PetscBool createInfo,CeedQFunctionUser func,const char * func_source,DMCeed * soldata,CeedQFunctionContext qfCtx)325354b609cSMatthew G. Knepley PetscErrorCode DMCeedCreateFVM_Internal(DM dm, IS faceIS, PetscBool createGeometry, PetscBool createInfo, CeedQFunctionUser func, const char *func_source, DMCeed *soldata, CeedQFunctionContext qfCtx)
3265962854dSMatthew G. Knepley {
3275962854dSMatthew G. Knepley   PetscDS  ds;
3285962854dSMatthew G. Knepley   PetscFV  fv;
3295962854dSMatthew G. Knepley   DMCeed   sd;
3305962854dSMatthew G. Knepley   Ceed     ceed;
331354b609cSMatthew G. Knepley   PetscInt dim, Nc, Nqdata = 0, Nqinfo = 0;
3325962854dSMatthew G. Knepley 
3335962854dSMatthew G. Knepley   PetscFunctionBegin;
3345962854dSMatthew G. Knepley   PetscCall(PetscCalloc1(1, &sd));
3355962854dSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
3365962854dSMatthew G. Knepley   PetscCall(DMGetCeed(dm, &ceed));
3375962854dSMatthew G. Knepley   PetscCall(DMGetDS(dm, &ds));
3385962854dSMatthew G. Knepley   PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fv));
3395962854dSMatthew G. Knepley   PetscCall(PetscFVGetNumComponents(fv, &Nc));
3405962854dSMatthew G. Knepley   PetscCall(DMPlexCreateCeedRestrictionFVM(dm, &sd->erL, &sd->erR));
3415962854dSMatthew G. Knepley 
3425962854dSMatthew G. Knepley   if (createGeometry) {
3435962854dSMatthew G. Knepley     DM cdm;
3445962854dSMatthew G. Knepley 
3455962854dSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
3465962854dSMatthew G. Knepley     PetscCall(DMCeedCreateGeometryFVM(cdm, faceIS, &Nqdata, &sd->erq, &sd->qd, &sd->geom));
3475962854dSMatthew G. Knepley   }
3485962854dSMatthew G. Knepley 
349354b609cSMatthew G. Knepley   if (createInfo) {
350354b609cSMatthew G. Knepley     DM cdm;
351354b609cSMatthew G. Knepley 
352354b609cSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
353354b609cSMatthew G. Knepley     PetscCall(DMCeedCreateInfoFVM(cdm, faceIS, &Nqinfo, &sd->eri, &sd->qi, &sd->info));
354354b609cSMatthew G. Knepley     PetscCall(DMCeedComputeInfo(dm, sd));
355354b609cSMatthew G. Knepley   }
356354b609cSMatthew G. Knepley 
3575962854dSMatthew G. Knepley   PetscCallCEED(CeedQFunctionCreateInterior(ceed, 1, func, func_source, &sd->qf));
3585962854dSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "uL", Nc, CEED_EVAL_NONE));
3595962854dSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "uR", Nc, CEED_EVAL_NONE));
3605962854dSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddInput(sd->qf, "geom", Nqdata, CEED_EVAL_NONE));
361354b609cSMatthew G. Knepley   if (createInfo) PetscCallCEED(CeedQFunctionAddInput(sd->qf, "info", Nqinfo, CEED_EVAL_NONE));
3625962854dSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddOutput(sd->qf, "cL", Nc, CEED_EVAL_NONE));
3635962854dSMatthew G. Knepley   PetscCallCEED(CeedQFunctionAddOutput(sd->qf, "cR", Nc, CEED_EVAL_NONE));
3645962854dSMatthew G. Knepley 
3655962854dSMatthew G. Knepley   PetscCallCEED(CeedQFunctionSetContext(sd->qf, qfCtx));
3665962854dSMatthew G. Knepley 
3675962854dSMatthew G. Knepley   PetscCallCEED(CeedOperatorCreate(ceed, sd->qf, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &sd->op));
36810ae67c6SJeremy L Thompson   PetscCallCEED(CeedOperatorSetField(sd->op, "uL", sd->erL, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
36910ae67c6SJeremy L Thompson   PetscCallCEED(CeedOperatorSetField(sd->op, "uR", sd->erR, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
37010ae67c6SJeremy L Thompson   PetscCallCEED(CeedOperatorSetField(sd->op, "geom", sd->erq, CEED_BASIS_NONE, sd->qd));
371354b609cSMatthew G. Knepley   if (createInfo) PetscCallCEED(CeedOperatorSetField(sd->op, "info", sd->eri, CEED_BASIS_NONE, sd->qi));
37210ae67c6SJeremy L Thompson   PetscCallCEED(CeedOperatorSetField(sd->op, "cL", sd->erL, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
37310ae67c6SJeremy L Thompson   PetscCallCEED(CeedOperatorSetField(sd->op, "cR", sd->erR, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
3745962854dSMatthew G. Knepley 
3755962854dSMatthew G. Knepley   // Handle refinement
3765962854dSMatthew G. Knepley   sd->func = func;
3775962854dSMatthew G. Knepley   PetscCall(PetscStrallocpy(func_source, &sd->funcSource));
3785962854dSMatthew G. Knepley   PetscCall(DMRefineHookAdd(dm, DMRefineHook_Ceed, NULL, NULL));
3795962854dSMatthew G. Knepley 
3805962854dSMatthew G. Knepley   *soldata = sd;
3815962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
3825962854dSMatthew G. Knepley }
3835962854dSMatthew G. Knepley 
DMCeedCreateFVM(DM dm,PetscBool createGeometry,CeedQFunctionUser func,const char * func_source,CeedQFunctionContext qfCtx)3845962854dSMatthew G. Knepley PetscErrorCode DMCeedCreateFVM(DM dm, PetscBool createGeometry, CeedQFunctionUser func, const char *func_source, CeedQFunctionContext qfCtx)
3855962854dSMatthew G. Knepley {
3865962854dSMatthew G. Knepley   DM plex;
3875962854dSMatthew G. Knepley   IS faceIS;
3885962854dSMatthew G. Knepley 
3895962854dSMatthew G. Knepley   PetscFunctionBegin;
3905962854dSMatthew G. Knepley   PetscCall(DMConvert(dm, DMPLEX, &plex));
3915962854dSMatthew G. Knepley   PetscCall(DMPlexGetAllFaces_Internal(plex, &faceIS));
3925962854dSMatthew G. Knepley   #ifdef PETSC_HAVE_LIBCEED
393354b609cSMatthew G. Knepley   PetscCall(DMCeedCreateFVM_Internal(dm, faceIS, createGeometry, PETSC_TRUE, func, func_source, &dm->dmceed, qfCtx));
3945962854dSMatthew G. Knepley   #endif
3955962854dSMatthew G. Knepley   PetscCall(ISDestroy(&faceIS));
3965962854dSMatthew G. Knepley   PetscCall(DMDestroy(&plex));
3975962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
3985962854dSMatthew G. Knepley }
3995962854dSMatthew G. Knepley 
400f918ec44SMatthew G. Knepley #endif
401d2b2dc1eSMatthew G. Knepley 
DMCeedDestroy(DMCeed * pceed)402d2b2dc1eSMatthew G. Knepley PetscErrorCode DMCeedDestroy(DMCeed *pceed)
403d2b2dc1eSMatthew G. Knepley {
404d2b2dc1eSMatthew G. Knepley   DMCeed p = *pceed;
405d2b2dc1eSMatthew G. Knepley 
406d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
407d2b2dc1eSMatthew G. Knepley   if (!p) PetscFunctionReturn(PETSC_SUCCESS);
408d2b2dc1eSMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
409d2b2dc1eSMatthew G. Knepley   PetscCall(PetscFree(p->funcSource));
410d2b2dc1eSMatthew G. Knepley   if (p->qd) PetscCallCEED(CeedVectorDestroy(&p->qd));
411354b609cSMatthew G. Knepley   if (p->qi) PetscCallCEED(CeedVectorDestroy(&p->qi));
412d2b2dc1eSMatthew G. Knepley   if (p->op) PetscCallCEED(CeedOperatorDestroy(&p->op));
413d2b2dc1eSMatthew G. Knepley   if (p->qf) PetscCallCEED(CeedQFunctionDestroy(&p->qf));
4145962854dSMatthew G. Knepley   if (p->erL) PetscCallCEED(CeedElemRestrictionDestroy(&p->erL));
4155962854dSMatthew G. Knepley   if (p->erR) PetscCallCEED(CeedElemRestrictionDestroy(&p->erR));
416d2b2dc1eSMatthew G. Knepley   if (p->erq) PetscCallCEED(CeedElemRestrictionDestroy(&p->erq));
417354b609cSMatthew G. Knepley   if (p->eri) PetscCallCEED(CeedElemRestrictionDestroy(&p->eri));
418d2b2dc1eSMatthew G. Knepley   PetscCall(DMCeedDestroy(&p->geom));
419354b609cSMatthew G. Knepley   PetscCall(DMCeedDestroy(&p->info));
420d2b2dc1eSMatthew G. Knepley #endif
421d2b2dc1eSMatthew G. Knepley   PetscCall(PetscFree(p));
422d2b2dc1eSMatthew G. Knepley   *pceed = NULL;
423d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
424d2b2dc1eSMatthew G. Knepley }
425d2b2dc1eSMatthew G. Knepley 
DMCeedComputeGeometry(DM dm,DMCeed sd)426d2b2dc1eSMatthew G. Knepley PetscErrorCode DMCeedComputeGeometry(DM dm, DMCeed sd)
427d2b2dc1eSMatthew G. Knepley {
428d2b2dc1eSMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
429d2b2dc1eSMatthew G. Knepley   Ceed       ceed;
430d2b2dc1eSMatthew G. Knepley   Vec        coords;
431d2b2dc1eSMatthew G. Knepley   CeedVector ccoords;
432d2b2dc1eSMatthew G. Knepley #endif
433d2b2dc1eSMatthew G. Knepley 
434d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
435d2b2dc1eSMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
436d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetCeed(dm, &ceed));
437d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetCoordinatesLocal(dm, &coords));
438d2b2dc1eSMatthew G. Knepley   PetscCall(VecGetCeedVectorRead(coords, ceed, &ccoords));
4395962854dSMatthew G. Knepley   if (sd->geom->op) PetscCallCEED(CeedOperatorApply(sd->geom->op, ccoords, sd->qd, CEED_REQUEST_IMMEDIATE));
4405962854dSMatthew G. Knepley   else PetscCall(DMPlexCeedComputeGeometryFVM(dm, sd->qd));
4415962854dSMatthew G. Knepley   //PetscCallCEED(CeedVectorView(sd->qd, "%g", stdout));
442d2b2dc1eSMatthew G. Knepley   PetscCall(VecRestoreCeedVectorRead(coords, &ccoords));
443d2b2dc1eSMatthew G. Knepley #endif
444d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
445d2b2dc1eSMatthew G. Knepley }
446354b609cSMatthew G. Knepley 
DMCeedComputeInfo(DM dm,DMCeed sd)447354b609cSMatthew G. Knepley PetscErrorCode DMCeedComputeInfo(DM dm, DMCeed sd)
448354b609cSMatthew G. Knepley {
449354b609cSMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
450354b609cSMatthew G. Knepley   CeedScalar *a;
451354b609cSMatthew G. Knepley #endif
452354b609cSMatthew G. Knepley 
453354b609cSMatthew G. Knepley   PetscFunctionBegin;
454354b609cSMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
455354b609cSMatthew G. Knepley   PetscCallCEED(CeedVectorGetArrayWrite(sd->qi, CEED_MEM_HOST, &a));
456354b609cSMatthew G. Knepley 
457354b609cSMatthew G. Knepley   IS              iterIS;
458354b609cSMatthew G. Knepley   DMLabel         label = NULL;
459354b609cSMatthew G. Knepley   const PetscInt *indices;
460354b609cSMatthew G. Knepley   PetscInt        value = 0, height = 1, NfInt = 0, Nf = 0;
461354b609cSMatthew G. Knepley 
462354b609cSMatthew G. Knepley   PetscCall(DMGetPoints_Internal(dm, label, value, height, &iterIS));
463354b609cSMatthew G. Knepley   if (iterIS) {
464354b609cSMatthew G. Knepley     PetscCall(ISGetIndices(iterIS, &indices));
465354b609cSMatthew G. Knepley     PetscCall(ISGetLocalSize(iterIS, &Nf));
466354b609cSMatthew G. Knepley     for (PetscInt p = 0, Ns; p < Nf; ++p) {
467354b609cSMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, indices[p], &Ns));
468354b609cSMatthew G. Knepley       if (Ns == 2) ++NfInt;
469354b609cSMatthew G. Knepley     }
470354b609cSMatthew G. Knepley   } else {
471354b609cSMatthew G. Knepley     indices = NULL;
472354b609cSMatthew G. Knepley   }
473354b609cSMatthew G. Knepley 
474354b609cSMatthew G. Knepley   PetscInt infoOffset = 0;
475354b609cSMatthew G. Knepley 
476354b609cSMatthew G. Knepley   for (PetscInt p = 0; p < Nf; ++p) {
477354b609cSMatthew G. Knepley     const PetscInt  face = indices[p];
478354b609cSMatthew G. Knepley     const PetscInt *supp;
479354b609cSMatthew G. Knepley     PetscInt        Ns;
480354b609cSMatthew G. Knepley 
481354b609cSMatthew G. Knepley     PetscCall(DMPlexGetSupport(dm, face, &supp));
482354b609cSMatthew G. Knepley     PetscCall(DMPlexGetSupportSize(dm, face, &Ns));
483354b609cSMatthew G. Knepley     // Ignore boundary faces
484354b609cSMatthew G. Knepley     //   TODO check for face on parallel boundary
485354b609cSMatthew G. Knepley     if (Ns == 2) {
486354b609cSMatthew G. Knepley       a[infoOffset++] = face;
487354b609cSMatthew G. Knepley       a[infoOffset++] = supp[0];
488354b609cSMatthew G. Knepley       a[infoOffset++] = supp[1];
489354b609cSMatthew G. Knepley     }
490354b609cSMatthew G. Knepley   }
491354b609cSMatthew G. Knepley   PetscCheck(infoOffset == NfInt * 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Shape mismatch, info offsets array of shape (%" PetscInt_FMT ") initialized for %" PetscInt_FMT " nodes", infoOffset, NfInt * 3);
492354b609cSMatthew G. Knepley   if (iterIS) PetscCall(ISRestoreIndices(iterIS, &indices));
493354b609cSMatthew G. Knepley   PetscCall(ISDestroy(&iterIS));
494354b609cSMatthew G. Knepley 
495354b609cSMatthew G. Knepley   PetscCallCEED(CeedVectorRestoreArray(sd->qi, &a));
496354b609cSMatthew G. Knepley #endif
497354b609cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
498354b609cSMatthew G. Knepley }
499