xref: /petsc/include/petsc/private/petscfeimpl.h (revision 287d9e588383f1e1baab2c4c0a0ac647a71c77d4) !
1 #pragma once
2 
3 #include <petscfe.h>
4 #ifdef PETSC_HAVE_LIBCEED
5   #include <petscfeceed.h>
6 #endif
7 #include <petscds.h>
8 #include <petsc/private/petscimpl.h>
9 #include <petsc/private/dmpleximpl.h>
10 
11 PETSC_EXTERN PetscBool      PetscSpaceRegisterAllCalled;
12 PETSC_EXTERN PetscBool      PetscDualSpaceRegisterAllCalled;
13 PETSC_EXTERN PetscBool      PetscFERegisterAllCalled;
14 PETSC_EXTERN PetscErrorCode PetscSpaceRegisterAll(void);
15 PETSC_EXTERN PetscErrorCode PetscDualSpaceRegisterAll(void);
16 PETSC_EXTERN PetscErrorCode PetscFERegisterAll(void);
17 
18 PETSC_INTERN PetscBool  FEcite;
19 PETSC_INTERN const char FECitation[];
20 
21 PETSC_EXTERN PetscLogEvent PETSCDUALSPACE_SetUp;
22 PETSC_EXTERN PetscLogEvent PETSCFE_SetUp;
23 
24 typedef struct _PetscSpaceOps *PetscSpaceOps;
25 struct _PetscSpaceOps {
26   PetscErrorCode (*setfromoptions)(PetscSpace, PetscOptionItems);
27   PetscErrorCode (*setup)(PetscSpace);
28   PetscErrorCode (*view)(PetscSpace, PetscViewer);
29   PetscErrorCode (*destroy)(PetscSpace);
30 
31   PetscErrorCode (*getdimension)(PetscSpace, PetscInt *);
32   PetscErrorCode (*evaluate)(PetscSpace, PetscInt, const PetscReal *, PetscReal *, PetscReal *, PetscReal *);
33   PetscErrorCode (*getheightsubspace)(PetscSpace, PetscInt, PetscSpace *);
34 };
35 
36 struct _p_PetscSpace {
37   PETSCHEADER(struct _PetscSpaceOps);
38   void    *data;      /* Implementation object */
39   PetscInt degree;    /* The approximation order of the space */
40   PetscInt maxDegree; /* The containing approximation order of the space */
41   PetscInt Nc;        /* The number of components */
42   PetscInt Nv;        /* The number of variables in the space, e.g. x and y */
43   PetscInt dim;       /* The dimension of the space */
44   DM       dm;        /* Shell to use for temp allocation */
45 };
46 
47 typedef struct {
48   PetscBool   tensor; /* Flag for tensor product */
49   PetscBool   setupcalled;
50   PetscSpace *subspaces; /* Subspaces for each dimension */
51 } PetscSpace_Poly;
52 
53 typedef struct {
54   PetscInt    formDegree;
55   PetscBool   setupcalled;
56   PetscSpace *subspaces;
57 } PetscSpace_Ptrimmed;
58 
59 typedef struct {
60   PetscSpace *tensspaces;
61   PetscInt    numTensSpaces;
62   PetscInt    dim;
63   PetscBool   uniform;
64   PetscBool   setupcalled;
65   PetscSpace *heightsubspaces; /* Height subspaces */
66 } PetscSpace_Tensor;
67 
68 typedef struct {
69   PetscSpace *sumspaces;
70   PetscInt    numSumSpaces;
71   PetscBool   uniform;
72   PetscBool   concatenate;
73   PetscBool   setupcalled;
74   PetscBool   interleave_basis;
75   PetscBool   interleave_components;
76   PetscSpace *heightsubspaces; /* Height subspaces */
77 } PetscSpace_Sum;
78 
79 typedef struct {
80   PetscQuadrature quad; /* The points defining the space */
81 } PetscSpace_Point;
82 
83 typedef struct {
84   PetscBool setupcalled;
85 } PetscSpace_WXY;
86 
87 typedef struct _PetscDualSpaceOps *PetscDualSpaceOps;
88 struct _PetscDualSpaceOps {
89   PetscErrorCode (*setfromoptions)(PetscDualSpace, PetscOptionItems);
90   PetscErrorCode (*setup)(PetscDualSpace);
91   PetscErrorCode (*view)(PetscDualSpace, PetscViewer);
92   PetscErrorCode (*destroy)(PetscDualSpace);
93 
94   PetscErrorCode (*duplicate)(PetscDualSpace, PetscDualSpace);
95   PetscErrorCode (*createheightsubspace)(PetscDualSpace, PetscInt, PetscDualSpace *);
96   PetscErrorCode (*createpointsubspace)(PetscDualSpace, PetscInt, PetscDualSpace *);
97   PetscErrorCode (*getsymmetries)(PetscDualSpace, const PetscInt ****, const PetscScalar ****);
98   PetscErrorCode (*apply)(PetscDualSpace, PetscInt, PetscReal, PetscFEGeom *, PetscInt, PetscErrorCode (*)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void *, PetscScalar *);
99   PetscErrorCode (*applyall)(PetscDualSpace, const PetscScalar *, PetscScalar *);
100   PetscErrorCode (*applyint)(PetscDualSpace, const PetscScalar *, PetscScalar *);
101   PetscErrorCode (*createalldata)(PetscDualSpace, PetscQuadrature *, Mat *);
102   PetscErrorCode (*createintdata)(PetscDualSpace, PetscQuadrature *, Mat *);
103 };
104 
105 struct _p_PetscDualSpace {
106   PETSCHEADER(struct _PetscDualSpaceOps);
107   void            *data;       /* Implementation object */
108   DM               dm;         /* The integration region K */
109   PetscInt         order;      /* The approximation order of the space */
110   PetscInt         Nc;         /* The number of components */
111   PetscQuadrature *functional; /* The basis of functionals for this space */
112   Mat              allMat;
113   PetscQuadrature  allNodes; /* Collects all quadrature points representing functionals in the basis */
114   Vec              allNodeValues;
115   Vec              allDofValues;
116   Mat              intMat;
117   PetscQuadrature  intNodes; /* Collects all quadrature points representing functionals in the basis in the interior of the cell */
118   Vec              intNodeValues;
119   Vec              intDofValues;
120   PetscInt         spdim;    /* The dual-space dimension */
121   PetscInt         spintdim; /* The dual-space interior dimension */
122   PetscInt         k;        /* k-simplex corresponding to the dofs in this basis (we always use the 3D complex right now) */
123   PetscBool        uniform;
124   PetscBool        setupcalled;
125   PetscBool        setfromoptionscalled;
126   PetscSection     pointSection;
127   PetscSection     intPointSection;
128   PetscDualSpace  *pointSpaces;
129   PetscDualSpace  *heightSpaces;
130   PetscInt        *numDof;
131 };
132 
133 typedef struct _n_Petsc1DNodeFamily   *Petsc1DNodeFamily;
134 typedef struct _n_PetscLagNodeIndices *PetscLagNodeIndices;
135 
136 PETSC_EXTERN PetscErrorCode PetscLagNodeIndicesGetData_Internal(PetscLagNodeIndices, PetscInt *, PetscInt *, PetscInt *, const PetscInt *[], const PetscReal *[]);
137 PETSC_EXTERN PetscErrorCode PetscDualSpaceCreateInteriorSymmetryMatrix_Lagrange(PetscDualSpace sp, PetscInt ornt, Mat *symMat);
138 
139 typedef struct {
140   /* these describe the types of dual spaces implemented */
141   PetscBool tensorCell;  /* Flag for tensor product cell */
142   PetscBool tensorSpace; /* Flag for tensor product space of polynomials, as opposed to a space of maximum degree */
143   PetscBool trimmed;     /* Flag for dual space of trimmed polynomial spaces */
144   PetscBool continuous;  /* Flag for a continuous basis, as opposed to discontinuous across element boundaries */
145 
146   PetscBool interiorOnly; /* To make setup faster for tensor elements, only construct interior dofs in recursive calls */
147 
148   /* these keep track of symmetries */
149   PetscInt    ***symperms;
150   PetscScalar ***symflips;
151   PetscInt       numSelfSym;
152   PetscInt       selfSymOff;
153   PetscBool      symComputed;
154 
155   /* these describe different schemes of placing nodes in a simplex, from
156    * which are derived all dofs in Lagrange dual spaces */
157   PetscDTNodeType   nodeType;
158   PetscBool         endNodes;
159   PetscReal         nodeExponent;
160   PetscInt          numNodeSkip; /* The number of end nodes from the 1D Node family to skip */
161   Petsc1DNodeFamily nodeFamily;
162 
163   PetscInt numCopies;
164 
165   PetscBool useMoments;  /* Use moments for functionals */
166   PetscInt  momentOrder; /* Order for moment quadrature */
167 
168   /* these are ways of indexing nodes in a way that makes
169    * the computation of symmetries programmatic */
170   PetscLagNodeIndices vertIndices;
171   PetscLagNodeIndices intNodeIndices;
172   PetscLagNodeIndices allNodeIndices;
173 } PetscDualSpace_Lag;
174 
175 typedef struct {
176   PetscDualSpace         *sumspaces;
177   PetscInt                numSumSpaces;
178   PetscBool               uniform;
179   PetscBool               uniform_all_points;
180   PetscBool               uniform_interior_points;
181   PetscBool               concatenate;
182   PetscBool               setupcalled;
183   PetscBool               interleave_basis;
184   PetscBool               interleave_components;
185   ISLocalToGlobalMapping *all_rows;
186   ISLocalToGlobalMapping *all_cols;
187   ISLocalToGlobalMapping *int_rows;
188   ISLocalToGlobalMapping *int_cols;
189 
190   PetscInt    ***symperms;
191   PetscScalar ***symflips;
192   PetscInt       numSelfSym;
193   PetscInt       selfSymOff;
194   PetscBool      symComputed;
195 } PetscDualSpace_Sum;
196 
197 typedef struct {
198   PetscInt  dim;
199   PetscInt *numDof;
200 } PetscDualSpace_Simple;
201 
202 typedef struct _PetscFEOps *PetscFEOps;
203 struct _PetscFEOps {
204   PetscErrorCode (*setfromoptions)(PetscFE, PetscOptionItems);
205   PetscErrorCode (*setup)(PetscFE);
206   PetscErrorCode (*view)(PetscFE, PetscViewer);
207   PetscErrorCode (*destroy)(PetscFE);
208   PetscErrorCode (*getdimension)(PetscFE, PetscInt *);
209   PetscErrorCode (*createpointtrace)(PetscFE, PetscInt, PetscFE *);
210   PetscErrorCode (*computetabulation)(PetscFE, PetscInt, const PetscReal *, PetscInt, PetscTabulation);
211   /* Element integration */
212   PetscErrorCode (*integrate)(PetscDS, PetscInt, PetscInt, PetscFEGeom *, const PetscScalar[], PetscDS, const PetscScalar[], PetscScalar[]);
213   PetscErrorCode (*integratebd)(PetscDS, PetscInt, PetscBdPointFn *, PetscInt, PetscFEGeom *, const PetscScalar[], PetscDS, const PetscScalar[], PetscScalar[]);
214   PetscErrorCode (*integrateresidual)(PetscDS, PetscFormKey, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscScalar[]);
215   PetscErrorCode (*integratebdresidual)(PetscDS, PetscWeakForm, PetscFormKey, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscScalar[]);
216   PetscErrorCode (*integratehybridresidual)(PetscDS, PetscDS, PetscFormKey, PetscInt, PetscInt, PetscFEGeom *, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscScalar[]);
217   PetscErrorCode (*integratejacobianaction)(PetscFE, PetscDS, PetscInt, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscReal, PetscScalar[]);
218   PetscErrorCode (*integratejacobian)(PetscDS, PetscDS, PetscFEJacobianType, PetscFormKey, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscReal, PetscScalar[]);
219   PetscErrorCode (*integratebdjacobian)(PetscDS, PetscWeakForm, PetscFEJacobianType, PetscFormKey, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscReal, PetscScalar[]);
220   PetscErrorCode (*integratehybridjacobian)(PetscDS, PetscDS, PetscFEJacobianType, PetscFormKey, PetscInt, PetscInt, PetscFEGeom *, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscReal, PetscScalar[]);
221 };
222 
223 struct _p_PetscFE {
224   PETSCHEADER(struct _PetscFEOps);
225   void           *data;                  /* Implementation object */
226   PetscSpace      basisSpace;            /* The basis space P */
227   PetscDualSpace  dualSpace;             /* The dual space P' */
228   PetscInt        numComponents;         /* The number of field components */
229   PetscQuadrature quadrature;            /* Suitable quadrature on K */
230   PetscQuadrature faceQuadrature;        /* Suitable face quadrature on \partial K */
231   PetscFE        *subspaces;             /* Subspaces for each dimension */
232   PetscReal      *invV;                  /* Change of basis matrix, from prime to nodal basis set */
233   PetscTabulation T;                     /* Tabulation of basis and derivatives at quadrature points */
234   PetscTabulation Tf;                    /* Tabulation of basis and derivatives at quadrature points on each face */
235   PetscTabulation Tc;                    /* Tabulation of basis at face centroids */
236   PetscInt        blockSize, numBlocks;  /* Blocks are processed concurrently */
237   PetscInt        batchSize, numBatches; /* A batch is made up of blocks, Batches are processed in serial */
238   PetscBool       setupcalled;
239 #ifdef PETSC_HAVE_LIBCEED
240   Ceed      ceed;      /* The LibCEED context, usually set by the DM */
241   CeedBasis ceedBasis; /* Basis for libCEED matching this element */
242 #endif
243 };
244 
245 typedef struct {
246   PetscInt cellType;
247 } PetscFE_Basic;
248 
249 #ifdef PETSC_HAVE_OPENCL
250 
251   #ifdef __APPLE__
252     #include <OpenCL/cl.h>
253   #else
254     #include <CL/cl.h>
255   #endif
256 
257 typedef struct {
258   cl_platform_id   pf_id;
259   cl_device_id     dev_id;
260   cl_context       ctx_id;
261   cl_command_queue queue_id;
262   PetscDataType    realType;
263   PetscLogEvent    residualEvent;
264   PetscInt         op; /* ANDY: Stand-in for real equation code generation */
265 } PetscFE_OpenCL;
266 #endif
267 
268 typedef struct {
269   PetscInt   numSubelements; /* The number of subelements */
270   PetscReal *v0;             /* The affine transformation for each subelement */
271   PetscReal *jac, *invjac;
272   PetscInt  *embedding; /* Map from subelements dofs to element dofs */
273 } PetscFE_Composite;
274 
275 /* Utility functions */
CoordinatesRefToReal(PetscInt dimReal,PetscInt dimRef,const PetscReal xi0[],const PetscReal v0[],const PetscReal J[],const PetscReal xi[],PetscReal x[])276 static inline void CoordinatesRefToReal(PetscInt dimReal, PetscInt dimRef, const PetscReal xi0[], const PetscReal v0[], const PetscReal J[], const PetscReal xi[], PetscReal x[])
277 {
278   PetscInt d, e;
279 
280   for (d = 0; d < dimReal; ++d) {
281     x[d] = v0[d];
282     for (e = 0; e < dimRef; ++e) x[d] += J[d * dimReal + e] * (xi[e] - xi0[e]);
283   }
284 }
285 
CoordinatesRealToRef(PetscInt dimReal,PetscInt dimRef,const PetscReal xi0[],const PetscReal v0[],const PetscReal invJ[],const PetscReal x[],PetscReal xi[])286 static inline void CoordinatesRealToRef(PetscInt dimReal, PetscInt dimRef, const PetscReal xi0[], const PetscReal v0[], const PetscReal invJ[], const PetscReal x[], PetscReal xi[])
287 {
288   PetscInt d, e;
289 
290   for (d = 0; d < dimRef; ++d) {
291     xi[d] = xi0[d];
292     for (e = 0; e < dimReal; ++e) xi[d] += invJ[d * dimReal + e] * (x[e] - v0[e]);
293   }
294 }
295 
PetscFEInterpolate_Static(PetscFE fe,const PetscScalar x[],PetscFEGeom * fegeom,PetscInt q,PetscScalar interpolant[])296 static inline PetscErrorCode PetscFEInterpolate_Static(PetscFE fe, const PetscScalar x[], PetscFEGeom *fegeom, PetscInt q, PetscScalar interpolant[])
297 {
298   PetscTabulation T;
299 
300   PetscFunctionBeginHot;
301   PetscCall(PetscFEGetCellTabulation(fe, 0, &T));
302   {
303     const PetscReal *basis = T->T[0];
304     const PetscInt   Nb    = T->Nb;
305     const PetscInt   Nc    = T->Nc;
306     for (PetscInt fc = 0; fc < Nc; ++fc) {
307       interpolant[fc] = 0.0;
308       for (PetscInt f = 0; f < Nb; ++f) interpolant[fc] += x[f] * basis[(q * Nb + f) * Nc + fc];
309     }
310   }
311   PetscCall(PetscFEPushforward(fe, fegeom, 1, interpolant));
312   PetscFunctionReturn(PETSC_SUCCESS);
313 }
314 
PetscFEInterpolateAtPoints_Static(PetscFE fe,PetscTabulation T,const PetscScalar x[],PetscFEGeom * fegeom,PetscInt q,PetscScalar interpolant[])315 static inline PetscErrorCode PetscFEInterpolateAtPoints_Static(PetscFE fe, PetscTabulation T, const PetscScalar x[], PetscFEGeom *fegeom, PetscInt q, PetscScalar interpolant[])
316 {
317   PetscInt fc, f;
318 
319   PetscFunctionBeginHot;
320   {
321     const PetscReal *basis = T->T[0];
322     const PetscInt   Nb    = T->Nb;
323     const PetscInt   Nc    = T->Nc;
324     for (fc = 0; fc < Nc; ++fc) {
325       interpolant[fc] = 0.0;
326       for (f = 0; f < Nb; ++f) interpolant[fc] += x[f] * basis[(q * Nb + f) * Nc + fc];
327     }
328   }
329   PetscCall(PetscFEPushforward(fe, fegeom, 1, interpolant));
330   PetscFunctionReturn(PETSC_SUCCESS);
331 }
332 
PetscFEInterpolateGradient_Static(PetscFE fe,PetscInt k,const PetscScalar x[],PetscFEGeom * fegeom,PetscInt q,PetscScalar interpolant[])333 static inline PetscErrorCode PetscFEInterpolateGradient_Static(PetscFE fe, PetscInt k, const PetscScalar x[], PetscFEGeom *fegeom, PetscInt q, PetscScalar interpolant[])
334 {
335   PetscTabulation T;
336   PetscInt        fc, f, d;
337 
338   PetscFunctionBeginHot;
339   PetscCall(PetscFEGetCellTabulation(fe, k, &T));
340   {
341     const PetscReal *basisDer = T->T[1];
342     const PetscReal *basisHes = k > 1 ? T->T[2] : NULL;
343     const PetscInt   Nb       = T->Nb;
344     const PetscInt   Nc       = T->Nc;
345     const PetscInt   cdim     = T->cdim;
346 
347     PetscCheck(cdim == fegeom->dimEmbed, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Geometry dim %" PetscInt_FMT " must match tabulation dim %" PetscInt_FMT, fegeom->dimEmbed, cdim);
348     for (fc = 0; fc < Nc; ++fc) {
349       for (d = 0; d < cdim; ++d) interpolant[fc * cdim + d] = 0.0;
350       for (f = 0; f < Nb; ++f) {
351         for (d = 0; d < cdim; ++d) interpolant[fc * cdim + d] += x[f] * basisDer[((q * Nb + f) * Nc + fc) * cdim + d];
352       }
353     }
354     if (k > 1) {
355       const PetscInt off = Nc * cdim;
356 
357       for (fc = 0; fc < Nc; ++fc) {
358         for (d = 0; d < cdim * cdim; ++d) interpolant[off + fc * cdim * cdim + d] = 0.0;
359         for (f = 0; f < Nb; ++f) {
360           for (d = 0; d < cdim * cdim; ++d) interpolant[off + fc * cdim + d] += x[f] * basisHes[((q * Nb + f) * Nc + fc) * cdim * cdim + d];
361         }
362       }
363     }
364   }
365   PetscCall(PetscFEPushforwardGradient(fe, fegeom, 1, interpolant));
366   PetscFunctionReturn(PETSC_SUCCESS);
367 }
368 
PetscFEFreeInterpolateGradient_Static(PetscFE fe,const PetscReal basisDer[],const PetscScalar x[],PetscInt dim,const PetscReal invJ[],const PetscReal n[],PetscInt q,PetscScalar interpolant[])369 static inline PetscErrorCode PetscFEFreeInterpolateGradient_Static(PetscFE fe, const PetscReal basisDer[], const PetscScalar x[], PetscInt dim, const PetscReal invJ[], const PetscReal n[], PetscInt q, PetscScalar interpolant[])
370 {
371   PetscReal   realSpaceDer[3];
372   PetscScalar compGradient[3];
373   PetscInt    Nb, Nc, fc, f, d, g;
374 
375   PetscFunctionBeginHot;
376   PetscCall(PetscFEGetDimension(fe, &Nb));
377   PetscCall(PetscFEGetNumComponents(fe, &Nc));
378 
379   for (fc = 0; fc < Nc; ++fc) {
380     interpolant[fc] = 0.0;
381     for (d = 0; d < dim; ++d) compGradient[d] = 0.0;
382     for (f = 0; f < Nb; ++f) {
383       for (d = 0; d < dim; ++d) {
384         realSpaceDer[d] = 0.0;
385         for (g = 0; g < dim; ++g) realSpaceDer[d] += invJ[g * dim + d] * basisDer[((q * Nb + f) * Nc + fc) * dim + g];
386         compGradient[d] += x[f] * realSpaceDer[d];
387       }
388     }
389     if (n) {
390       for (d = 0; d < dim; ++d) interpolant[fc] += compGradient[d] * n[d];
391     } else {
392       for (d = 0; d < dim; ++d) interpolant[d] = compGradient[d];
393     }
394   }
395   PetscFunctionReturn(PETSC_SUCCESS);
396 }
397 
PetscFEInterpolateFieldAndGradient_Static(PetscFE fe,PetscInt k,const PetscScalar x[],PetscFEGeom * fegeom,PetscInt q,PetscScalar interpolant[],PetscScalar interpolantGrad[])398 static inline PetscErrorCode PetscFEInterpolateFieldAndGradient_Static(PetscFE fe, PetscInt k, const PetscScalar x[], PetscFEGeom *fegeom, PetscInt q, PetscScalar interpolant[], PetscScalar interpolantGrad[])
399 {
400   PetscTabulation T;
401   PetscInt        fc, f, d;
402 
403   PetscFunctionBeginHot;
404   PetscCall(PetscFEGetCellTabulation(fe, k, &T));
405   {
406     const PetscReal *basis    = T->T[0];
407     const PetscReal *basisDer = T->T[1];
408     const PetscReal *basisHes = k > 1 ? T->T[2] : NULL;
409     const PetscInt   Nb       = T->Nb;
410     const PetscInt   Nc       = T->Nc;
411     const PetscInt   cdim     = T->cdim;
412 
413     PetscCheck(cdim == fegeom->dimEmbed, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Geometry dim %" PetscInt_FMT " must match tabulation dim %" PetscInt_FMT, fegeom->dimEmbed, cdim);
414     for (fc = 0; fc < Nc; ++fc) {
415       interpolant[fc] = 0.0;
416       for (d = 0; d < cdim; ++d) interpolantGrad[fc * cdim + d] = 0.0;
417       for (f = 0; f < Nb; ++f) {
418         interpolant[fc] += x[f] * basis[(q * Nb + f) * Nc + fc];
419         for (d = 0; d < cdim; ++d) interpolantGrad[fc * cdim + d] += x[f] * basisDer[((q * Nb + f) * Nc + fc) * cdim + d];
420       }
421     }
422     if (k > 1) {
423       const PetscInt off = Nc * cdim;
424 
425       for (fc = 0; fc < Nc; ++fc) {
426         for (d = 0; d < cdim * cdim; ++d) interpolantGrad[off + fc * cdim * cdim + d] = 0.0;
427         for (f = 0; f < Nb; ++f) {
428           for (d = 0; d < cdim * cdim; ++d) interpolantGrad[off + fc * cdim + d] += x[f] * basisHes[((q * Nb + f) * Nc + fc) * cdim * cdim + d];
429         }
430       }
431       PetscCall(PetscFEPushforwardHessian(fe, fegeom, 1, &interpolantGrad[off]));
432     }
433   }
434   PetscCall(PetscFEPushforward(fe, fegeom, 1, interpolant));
435   PetscCall(PetscFEPushforwardGradient(fe, fegeom, 1, interpolantGrad));
436   PetscFunctionReturn(PETSC_SUCCESS);
437 }
438 
439 PETSC_INTERN PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt, PetscInt, PetscInt[]);
440 PETSC_INTERN PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt, PetscInt, PetscInt[]);
441 PETSC_INTERN PetscErrorCode PetscDualSpaceComputeFunctionalsFromAllData(PetscDualSpace);
442 PETSC_INTERN PetscErrorCode PetscDualSpaceGetBoundarySymmetries_Internal(PetscDualSpace, PetscInt ***, PetscScalar ***);
443 
444 PETSC_INTERN PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace, PetscSection *);
445 PETSC_INTERN PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace, PetscSection);
446 PETSC_INTERN PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace, PetscInt, PetscInt);
447 
448 PETSC_INTERN PetscErrorCode PetscFEEvaluateFieldJets_Internal(PetscDS, PetscInt, PetscInt, PetscInt, PetscTabulation[], PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscScalar[], PetscScalar[], PetscScalar[]);
449 PETSC_INTERN PetscErrorCode PetscFEEvaluateFaceFields_Internal(PetscDS, PetscInt, PetscInt, const PetscScalar[], PetscScalar[]);
450 PETSC_INTERN PetscErrorCode PetscFEUpdateElementVec_Internal(PetscFE, PetscTabulation, PetscInt, PetscScalar[], PetscScalar[], PetscInt, PetscFEGeom *, PetscScalar[], PetscScalar[], PetscScalar[]);
451 PETSC_INTERN PetscErrorCode PetscFEUpdateElementMat_Internal(PetscFE, PetscFE, PetscInt, PetscInt, PetscTabulation, PetscScalar[], PetscScalar[], PetscTabulation, PetscScalar[], PetscScalar[], PetscFEGeom *, const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscInt, PetscInt, PetscInt, PetscScalar[]);
452 
453 PETSC_INTERN PetscErrorCode PetscFEEvaluateFieldJets_Hybrid_Internal(PetscDS, PetscInt, PetscInt, PetscInt, PetscTabulation[], const PetscInt[], const PetscInt[], PetscTabulation[], PetscFEGeom *, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscScalar[], PetscScalar[], PetscScalar[]);
454 PETSC_INTERN PetscErrorCode PetscFEUpdateElementVec_Hybrid_Internal(PetscFE, PetscTabulation, PetscInt, PetscInt, PetscScalar[], PetscScalar[], PetscFEGeom *, PetscScalar[], PetscScalar[], PetscScalar[]);
455 PETSC_INTERN PetscErrorCode PetscFEUpdateElementMat_Hybrid_Internal(PetscFE, PetscBool, PetscFE, PetscBool, PetscInt, PetscInt, PetscInt, PetscInt, PetscTabulation, PetscScalar[], PetscScalar[], PetscTabulation, PetscScalar[], PetscScalar[], PetscFEGeom *, const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscInt, PetscInt, PetscInt, PetscInt, PetscScalar[]);
456 
457 PETSC_INTERN PetscErrorCode PetscFEGetDimension_Basic(PetscFE, PetscInt *);
458 PETSC_INTERN PetscErrorCode PetscFEIntegrateResidual_Basic(PetscDS, PetscFormKey, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscScalar[]);
459 PETSC_INTERN PetscErrorCode PetscFEIntegrateBdResidual_Basic(PetscDS, PetscWeakForm, PetscFormKey, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscScalar[]);
460 PETSC_INTERN PetscErrorCode PetscFEIntegrateJacobian_Basic(PetscDS, PetscDS, PetscFEJacobianType, PetscFormKey, PetscInt, PetscFEGeom *, const PetscScalar[], const PetscScalar[], PetscDS, const PetscScalar[], PetscReal, PetscReal, PetscScalar[]);
461