xref: /petsc/src/dm/impls/plex/plexproject.c (revision 57508ece14a6b1339c0bbf016ecd72f673a062b0)
147923291SMatthew G. Knepley #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
247923291SMatthew G. Knepley 
38c6c5593SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>
48c6c5593SMatthew G. Knepley 
51b32699bSMatthew G. Knepley /*@
61b32699bSMatthew G. Knepley   DMPlexGetActivePoint - Get the point on which projection is currently working
71b32699bSMatthew G. Knepley 
820f4b53cSBarry Smith   Not Collective
91b32699bSMatthew G. Knepley 
104165533cSJose E. Roman   Input Parameter:
11a1cb98faSBarry Smith . dm - the `DM`
121b32699bSMatthew G. Knepley 
134165533cSJose E. Roman   Output Parameter:
141b32699bSMatthew G. Knepley . point - The mesh point involved in the current projection
151b32699bSMatthew G. Knepley 
161b32699bSMatthew G. Knepley   Level: developer
171b32699bSMatthew G. Knepley 
181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetActivePoint()`
191b32699bSMatthew G. Knepley @*/
20d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetActivePoint(DM dm, PetscInt *point)
21d71ae5a4SJacob Faibussowitsch {
221b32699bSMatthew G. Knepley   PetscFunctionBeginHot;
231b32699bSMatthew G. Knepley   *point = ((DM_Plex *)dm->data)->activePoint;
243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
251b32699bSMatthew G. Knepley }
261b32699bSMatthew G. Knepley 
271b32699bSMatthew G. Knepley /*@
281b32699bSMatthew G. Knepley   DMPlexSetActivePoint - Set the point on which projection is currently working
291b32699bSMatthew G. Knepley 
3020f4b53cSBarry Smith   Not Collective
311b32699bSMatthew G. Knepley 
324165533cSJose E. Roman   Input Parameters:
33a1cb98faSBarry Smith + dm    - the `DM`
341b32699bSMatthew G. Knepley - point - The mesh point involved in the current projection
351b32699bSMatthew G. Knepley 
361b32699bSMatthew G. Knepley   Level: developer
371b32699bSMatthew G. Knepley 
381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetActivePoint()`
391b32699bSMatthew G. Knepley @*/
40d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetActivePoint(DM dm, PetscInt point)
41d71ae5a4SJacob Faibussowitsch {
421b32699bSMatthew G. Knepley   PetscFunctionBeginHot;
431b32699bSMatthew G. Knepley   ((DM_Plex *)dm->data)->activePoint = point;
443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
451b32699bSMatthew G. Knepley }
461b32699bSMatthew G. Knepley 
47a6e0b375SMatthew G. Knepley /*
48a6e0b375SMatthew G. Knepley   DMProjectPoint_Func_Private - Interpolate the given function in the output basis on the given point
49a6e0b375SMatthew G. Knepley 
50a6e0b375SMatthew G. Knepley   Input Parameters:
51a1cb98faSBarry Smith + dm     - The output `DM`
52a1cb98faSBarry Smith . ds     - The output `DS`
53a1cb98faSBarry Smith . dmIn   - The input `DM`
54a1cb98faSBarry Smith . dsIn   - The input `DS`
55a6e0b375SMatthew G. Knepley . time   - The time for this evaluation
56a6e0b375SMatthew G. Knepley . fegeom - The FE geometry for this point
57a6e0b375SMatthew G. Knepley . fvgeom - The FV geometry for this point
58a6e0b375SMatthew G. Knepley . isFE   - Flag indicating whether each output field has an FE discretization
59a1cb98faSBarry Smith . sp     - The output `PetscDualSpace` for each field
60a6e0b375SMatthew G. Knepley . funcs  - The evaluation function for each field
61a6e0b375SMatthew G. Knepley - ctxs   - The user context for each field
62a6e0b375SMatthew G. Knepley 
63a6e0b375SMatthew G. Knepley   Output Parameter:
64a6e0b375SMatthew G. Knepley . values - The value for each dual basis vector in the output dual space
65a6e0b375SMatthew G. Knepley 
66a6e0b375SMatthew G. Knepley   Level: developer
67a6e0b375SMatthew G. Knepley 
681cc06b55SBarry Smith .seealso:[](ch_unstructured), `DM`, `DMPLEX`, `PetscDS`, `PetscFEGeom`, `PetscFVCellGeom`, `PetscDualSpace`
69a6e0b375SMatthew G. Knepley */
70d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectPoint_Func_Private(DM dm, PetscDS ds, DM dmIn, PetscDS dsIn, PetscReal time, PetscFEGeom *fegeom, PetscFVCellGeom *fvgeom, PetscBool isFE[], PetscDualSpace sp[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, PetscScalar values[])
71d71ae5a4SJacob Faibussowitsch {
72a6e0b375SMatthew G. Knepley   PetscInt  coordDim, Nf, *Nc, f, spDim, d, v, tp;
735fedec97SMatthew G. Knepley   PetscBool isAffine, isCohesive, transform;
748c6c5593SMatthew G. Knepley 
758c6c5593SMatthew G. Knepley   PetscFunctionBeginHot;
769566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmIn, &coordDim));
779566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dmIn, &transform));
789566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
799566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
809566063dSJacob Faibussowitsch   PetscCall(PetscDSIsCohesive(ds, &isCohesive));
818c6c5593SMatthew G. Knepley   /* Get values for closure */
82c330f8ffSToby Isaac   isAffine = fegeom->isAffine;
83c330f8ffSToby Isaac   for (f = 0, v = 0, tp = 0; f < Nf; ++f) {
848c6c5593SMatthew G. Knepley     void *const ctx = ctxs ? ctxs[f] : NULL;
855fedec97SMatthew G. Knepley     PetscBool   cohesive;
868c6c5593SMatthew G. Knepley 
878c6c5593SMatthew G. Knepley     if (!sp[f]) continue;
889566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
899566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDimension(sp[f], &spDim));
908c6c5593SMatthew G. Knepley     if (funcs[f]) {
91c330f8ffSToby Isaac       if (isFE[f]) {
92c330f8ffSToby Isaac         PetscQuadrature  allPoints;
93c330f8ffSToby Isaac         PetscInt         q, dim, numPoints;
94c330f8ffSToby Isaac         const PetscReal *points;
95c330f8ffSToby Isaac         PetscScalar     *pointEval;
96c330f8ffSToby Isaac         PetscReal       *x;
97ca3d3a14SMatthew G. Knepley         DM               rdm;
98c330f8ffSToby Isaac 
999566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetDM(sp[f], &rdm));
1009566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL));
1019566063dSJacob Faibussowitsch         PetscCall(PetscQuadratureGetData(allPoints, &dim, NULL, &numPoints, &points, NULL));
1029566063dSJacob Faibussowitsch         PetscCall(DMGetWorkArray(rdm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
1039566063dSJacob Faibussowitsch         PetscCall(DMGetWorkArray(rdm, coordDim, MPIU_REAL, &x));
104737e23dcSMatthew G. Knepley         PetscCall(PetscArrayzero(pointEval, numPoints * Nc[f]));
105c330f8ffSToby Isaac         for (q = 0; q < numPoints; q++, tp++) {
106c330f8ffSToby Isaac           const PetscReal *v0;
107c330f8ffSToby Isaac 
108c330f8ffSToby Isaac           if (isAffine) {
109665f567fSMatthew G. Knepley             const PetscReal *refpoint    = &points[q * dim];
110665f567fSMatthew G. Knepley             PetscReal        injpoint[3] = {0., 0., 0.};
111665f567fSMatthew G. Knepley 
112665f567fSMatthew G. Knepley             if (dim != fegeom->dim) {
1135fedec97SMatthew G. Knepley               if (isCohesive) {
114665f567fSMatthew G. Knepley                 /* We just need to inject into the higher dimensional space assuming the last dimension is collapsed */
115665f567fSMatthew G. Knepley                 for (d = 0; d < dim; ++d) injpoint[d] = refpoint[d];
116665f567fSMatthew G. Knepley                 refpoint = injpoint;
11763a3b9bcSJacob Faibussowitsch               } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reference spatial dimension %" PetscInt_FMT " != %" PetscInt_FMT " dual basis spatial dimension", fegeom->dim, dim);
118665f567fSMatthew G. Knepley             }
119665f567fSMatthew G. Knepley             CoordinatesRefToReal(coordDim, fegeom->dim, fegeom->xi, fegeom->v, fegeom->J, refpoint, x);
120c330f8ffSToby Isaac             v0 = x;
1218c6c5593SMatthew G. Knepley           } else {
122c330f8ffSToby Isaac             v0 = &fegeom->v[tp * coordDim];
1238c6c5593SMatthew G. Knepley           }
1249371c9d4SSatish Balay           if (transform) {
1259371c9d4SSatish Balay             PetscCall(DMPlexBasisTransformApplyReal_Internal(dmIn, v0, PETSC_TRUE, coordDim, v0, x, dm->transformCtx));
1269371c9d4SSatish Balay             v0 = x;
1279371c9d4SSatish Balay           }
1289566063dSJacob Faibussowitsch           PetscCall((*funcs[f])(coordDim, time, v0, Nc[f], &pointEval[Nc[f] * q], ctx));
129c330f8ffSToby Isaac         }
1304bee2e38SMatthew G. Knepley         /* Transform point evaluations pointEval[q,c] */
1319566063dSJacob Faibussowitsch         PetscCall(PetscDualSpacePullback(sp[f], fegeom, numPoints, Nc[f], pointEval));
1329566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v]));
1339566063dSJacob Faibussowitsch         PetscCall(DMRestoreWorkArray(rdm, coordDim, MPIU_REAL, &x));
1349566063dSJacob Faibussowitsch         PetscCall(DMRestoreWorkArray(rdm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
135c330f8ffSToby Isaac         v += spDim;
1365fedec97SMatthew G. Knepley         if (isCohesive && !cohesive) {
13727f02ce8SMatthew G. Knepley           for (d = 0; d < spDim; d++, v++) values[v] = values[v - spDim];
13827f02ce8SMatthew G. Knepley         }
139c330f8ffSToby Isaac       } else {
14048a46eb9SPierre Jolivet         for (d = 0; d < spDim; ++d, ++v) PetscCall(PetscDualSpaceApplyFVM(sp[f], d, time, fvgeom, Nc[f], funcs[f], ctx, &values[v]));
141c330f8ffSToby Isaac       }
142c330f8ffSToby Isaac     } else {
14327f02ce8SMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = 0.;
1445fedec97SMatthew G. Knepley       if (isCohesive && !cohesive) {
14527f02ce8SMatthew G. Knepley         for (d = 0; d < spDim; d++, v++) values[v] = 0.;
14627f02ce8SMatthew G. Knepley       }
1478c6c5593SMatthew G. Knepley     }
1489c3cf19fSMatthew G. Knepley   }
1493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1508c6c5593SMatthew G. Knepley }
1518c6c5593SMatthew G. Knepley 
152a6e0b375SMatthew G. Knepley /*
153a6e0b375SMatthew G. Knepley   DMProjectPoint_Field_Private - Interpolate a function of the given field, in the input basis, using the output basis on the given point
154a6e0b375SMatthew G. Knepley 
155a6e0b375SMatthew G. Knepley   Input Parameters:
156a6e0b375SMatthew G. Knepley + dm             - The output DM
157a6e0b375SMatthew G. Knepley . ds             - The output DS
158a6e0b375SMatthew G. Knepley . dmIn           - The input DM
159a6e0b375SMatthew G. Knepley . dsIn           - The input DS
160a6e0b375SMatthew G. Knepley . dmAux          - The auxiliary DM, which is always for the input space
161a6e0b375SMatthew G. Knepley . dsAux          - The auxiliary DS, which is always for the input space
162a6e0b375SMatthew G. Knepley . time           - The time for this evaluation
163a6e0b375SMatthew G. Knepley . localU         - The local solution
164a6e0b375SMatthew G. Knepley . localA         - The local auziliary fields
165a6e0b375SMatthew G. Knepley . cgeom          - The FE geometry for this point
166a6e0b375SMatthew G. Knepley . sp             - The output PetscDualSpace for each field
167a6e0b375SMatthew G. Knepley . p              - The point in the output DM
168a5b23f4aSJose E. Roman . T              - Input basis and derivatives for each field tabulated on the quadrature points
169ef0bb6c7SMatthew G. Knepley . TAux           - Auxiliary basis and derivatives for each aux field tabulated on the quadrature points
170a6e0b375SMatthew G. Knepley . funcs          - The evaluation function for each field
171a6e0b375SMatthew G. Knepley - ctxs           - The user context for each field
172a6e0b375SMatthew G. Knepley 
173a6e0b375SMatthew G. Knepley   Output Parameter:
174a6e0b375SMatthew G. Knepley . values         - The value for each dual basis vector in the output dual space
175a6e0b375SMatthew G. Knepley 
176a6e0b375SMatthew G. Knepley   Level: developer
177a6e0b375SMatthew G. Knepley 
178a1cb98faSBarry Smith   Note:
179a1cb98faSBarry Smith   Not supported for FV
180a1cb98faSBarry Smith 
181db781477SPatrick Sanan .seealso: `DMProjectPoint_Field_Private()`
182a6e0b375SMatthew G. Knepley */
183d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectPoint_Field_Private(DM dm, PetscDS ds, DM dmIn, DMEnclosureType encIn, PetscDS dsIn, DM dmAux, DMEnclosureType encAux, PetscDS dsAux, PetscReal time, Vec localU, Vec localA, PetscFEGeom *cgeom, PetscDualSpace sp[], PetscInt p, PetscTabulation *T, PetscTabulation *TAux, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), void **ctxs, PetscScalar values[])
184d71ae5a4SJacob Faibussowitsch {
1858c6c5593SMatthew G. Knepley   PetscSection       section, sectionAux = NULL;
1864bee2e38SMatthew G. Knepley   PetscScalar       *u, *u_t = NULL, *u_x, *a = NULL, *a_t = NULL, *a_x = NULL, *bc;
1878c6c5593SMatthew G. Knepley   PetscScalar       *coefficients = NULL, *coefficientsAux = NULL;
1888c6c5593SMatthew G. Knepley   PetscScalar       *coefficients_t = NULL, *coefficientsAux_t = NULL;
189191494d9SMatthew G. Knepley   const PetscScalar *constants;
1908c6c5593SMatthew G. Knepley   PetscReal         *x;
1918e6d238bSMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nc, face[2];
1924bee2e38SMatthew G. Knepley   PetscFEGeom        fegeom;
1938e6d238bSMatthew G. Knepley   const PetscInt     dE = cgeom->dimEmbed, *cone, *ornt;
194ef0bb6c7SMatthew G. Knepley   PetscInt           numConstants, Nf, NfIn, NfAux = 0, f, spDim, d, v, inp, tp = 0;
1958e6d238bSMatthew G. Knepley   PetscBool          isAffine, isCohesive, isCohesiveIn, transform;
1968e6d238bSMatthew G. Knepley   DMPolytopeType     qct;
1978c6c5593SMatthew G. Knepley 
1988c6c5593SMatthew G. Knepley   PetscFunctionBeginHot;
1999566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
2009566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
2019566063dSJacob Faibussowitsch   PetscCall(PetscDSIsCohesive(ds, &isCohesive));
2029566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(dsIn, &NfIn));
2038e6d238bSMatthew G. Knepley   PetscCall(PetscDSIsCohesive(dsIn, &isCohesiveIn));
2049566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponentOffsets(dsIn, &uOff));
2059566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponentDerivativeOffsets(dsIn, &uOff_x));
2069566063dSJacob Faibussowitsch   PetscCall(PetscDSGetEvaluationArrays(dsIn, &u, &bc /*&u_t*/, &u_x));
2079566063dSJacob Faibussowitsch   PetscCall(PetscDSGetWorkspace(dsIn, &x, NULL, NULL, NULL, NULL));
2089566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(dsIn, &numConstants, &constants));
2099566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dmIn, &transform));
2109566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmIn, &section));
2119566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosurePoint(dmIn, dm, encIn, p, &inp));
2128e6d238bSMatthew G. Knepley   // Get cohesive cell hanging off face
2138e6d238bSMatthew G. Knepley   if (isCohesiveIn) {
2148e6d238bSMatthew G. Knepley     PetscCall(DMPlexGetCellType(dmIn, inp, &qct));
2158e6d238bSMatthew G. Knepley     if ((qct != DM_POLYTOPE_POINT_PRISM_TENSOR) && (qct != DM_POLYTOPE_SEG_PRISM_TENSOR) && (qct != DM_POLYTOPE_TRI_PRISM_TENSOR) && (qct != DM_POLYTOPE_QUAD_PRISM_TENSOR)) {
2168e6d238bSMatthew G. Knepley       DMPolytopeType  ct;
2178e6d238bSMatthew G. Knepley       const PetscInt *support;
2188e6d238bSMatthew G. Knepley       PetscInt        Ns, s;
2198e6d238bSMatthew G. Knepley 
2208e6d238bSMatthew G. Knepley       PetscCall(DMPlexGetSupport(dmIn, inp, &support));
2218e6d238bSMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dmIn, inp, &Ns));
2228e6d238bSMatthew G. Knepley       for (s = 0; s < Ns; ++s) {
2238e6d238bSMatthew G. Knepley         PetscCall(DMPlexGetCellType(dmIn, support[s], &ct));
2248e6d238bSMatthew G. Knepley         if ((ct == DM_POLYTOPE_POINT_PRISM_TENSOR) || (ct == DM_POLYTOPE_SEG_PRISM_TENSOR) || (ct == DM_POLYTOPE_TRI_PRISM_TENSOR) || (ct == DM_POLYTOPE_QUAD_PRISM_TENSOR)) {
2258e6d238bSMatthew G. Knepley           inp = support[s];
2268e6d238bSMatthew G. Knepley           break;
2278e6d238bSMatthew G. Knepley         }
2288e6d238bSMatthew G. Knepley       }
2298e6d238bSMatthew G. Knepley       PetscCheck(s < Ns, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cell not found from face %" PetscInt_FMT, inp);
2308e6d238bSMatthew G. Knepley       PetscCall(PetscDSGetComponentOffsetsCohesive(dsIn, 2, &uOff));
2318e6d238bSMatthew G. Knepley       PetscCall(DMPlexGetOrientedCone(dmIn, inp, &cone, &ornt));
2328e6d238bSMatthew G. Knepley       face[0] = 0;
2338e6d238bSMatthew G. Knepley       face[1] = 0;
2348e6d238bSMatthew G. Knepley     }
2358e6d238bSMatthew G. Knepley   }
236eb8f539aSJed Brown   if (localU) PetscCall(DMPlexVecGetClosure(dmIn, section, localU, inp, NULL, &coefficients));
2378c6c5593SMatthew G. Knepley   if (dmAux) {
23844171101SMatthew G. Knepley     PetscInt subp;
2391ba34526SMatthew G. Knepley 
2409566063dSJacob Faibussowitsch     PetscCall(DMGetEnclosurePoint(dmAux, dm, encAux, p, &subp));
2419566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(dsAux, &NfAux));
2429566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dmAux, &sectionAux));
2439566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff));
2449566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x));
2459566063dSJacob Faibussowitsch     PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL /*&a_t*/, &a_x));
2469566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmAux, sectionAux, localA, subp, NULL, &coefficientsAux));
2478c6c5593SMatthew G. Knepley   }
2488c6c5593SMatthew G. Knepley   /* Get values for closure */
2494bee2e38SMatthew G. Knepley   isAffine        = cgeom->isAffine;
25027f02ce8SMatthew G. Knepley   fegeom.dim      = cgeom->dim;
25127f02ce8SMatthew G. Knepley   fegeom.dimEmbed = cgeom->dimEmbed;
2524bee2e38SMatthew G. Knepley   if (isAffine) {
2534bee2e38SMatthew G. Knepley     fegeom.v    = x;
2544bee2e38SMatthew G. Knepley     fegeom.xi   = cgeom->xi;
2554bee2e38SMatthew G. Knepley     fegeom.J    = cgeom->J;
2564bee2e38SMatthew G. Knepley     fegeom.invJ = cgeom->invJ;
2574bee2e38SMatthew G. Knepley     fegeom.detJ = cgeom->detJ;
2584bee2e38SMatthew G. Knepley   }
2598c6c5593SMatthew G. Knepley   for (f = 0, v = 0; f < Nf; ++f) {
260c330f8ffSToby Isaac     PetscQuadrature  allPoints;
261c330f8ffSToby Isaac     PetscInt         q, dim, numPoints;
262c330f8ffSToby Isaac     const PetscReal *points;
263c330f8ffSToby Isaac     PetscScalar     *pointEval;
2645fedec97SMatthew G. Knepley     PetscBool        cohesive;
265c330f8ffSToby Isaac     DM               dm;
266c330f8ffSToby Isaac 
2678c6c5593SMatthew G. Knepley     if (!sp[f]) continue;
2689566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
2699566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDimension(sp[f], &spDim));
270c330f8ffSToby Isaac     if (!funcs[f]) {
271be1504a2SMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = 0.;
2725fedec97SMatthew G. Knepley       if (isCohesive && !cohesive) {
27327f02ce8SMatthew G. Knepley         for (d = 0; d < spDim; d++, v++) values[v] = 0.;
27427f02ce8SMatthew G. Knepley       }
275c330f8ffSToby Isaac       continue;
276c330f8ffSToby Isaac     }
2776f0e67eaSMatthew G. Knepley     const PetscInt ***perms;
2789566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDM(sp[f], &dm));
2796f0e67eaSMatthew G. Knepley     PetscCall(PetscDualSpaceGetSymmetries(sp[f], &perms, NULL));
2809566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL));
2819566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(allPoints, &dim, NULL, &numPoints, &points, NULL));
2829566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
2830c898c18SMatthew G. Knepley     for (q = 0; q < numPoints; ++q, ++tp) {
2848e6d238bSMatthew G. Knepley       PetscInt qpt[2];
2858e6d238bSMatthew G. Knepley 
2868e6d238bSMatthew G. Knepley       if (isCohesiveIn) {
2876f0e67eaSMatthew G. Knepley         qpt[0] = perms ? perms[0][ornt[0]][q] : q;
2886f0e67eaSMatthew G. Knepley         qpt[1] = perms ? perms[0][DMPolytopeTypeComposeOrientationInv(qct, ornt[1], 0)][q] : q;
2898e6d238bSMatthew G. Knepley       }
290c330f8ffSToby Isaac       if (isAffine) {
291ef0bb6c7SMatthew G. Knepley         CoordinatesRefToReal(dE, cgeom->dim, fegeom.xi, cgeom->v, fegeom.J, &points[q * dim], x);
2921c531cf8SMatthew G. Knepley       } else {
2934bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[tp * dE];
2944bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[tp * dE * dE];
2954bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[tp * dE * dE];
2964bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[tp];
2978c6c5593SMatthew G. Knepley       }
2988e6d238bSMatthew G. Knepley       if (coefficients) {
2998e6d238bSMatthew G. Knepley         if (isCohesiveIn) PetscCall(PetscFEEvaluateFieldJets_Hybrid_Internal(dsIn, NfIn, 0, tp, T, face, qpt, T, &fegeom, coefficients, coefficients_t, u, u_x, u_t));
3008e6d238bSMatthew G. Knepley         else PetscCall(PetscFEEvaluateFieldJets_Internal(dsIn, NfIn, 0, tp, T, &fegeom, coefficients, coefficients_t, u, u_x, u_t));
3018e6d238bSMatthew G. Knepley       }
3029566063dSJacob Faibussowitsch       if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, tp, TAux, &fegeom, coefficientsAux, coefficientsAux_t, a, a_x, a_t));
3039566063dSJacob Faibussowitsch       if (transform) PetscCall(DMPlexBasisTransformApplyReal_Internal(dmIn, fegeom.v, PETSC_TRUE, dE, fegeom.v, fegeom.v, dm->transformCtx));
304a6e0b375SMatthew G. Knepley       (*funcs[f])(dE, NfIn, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, time, fegeom.v, numConstants, constants, &pointEval[Nc[f] * q]);
3051c531cf8SMatthew G. Knepley     }
3069566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v]));
3079566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
308c330f8ffSToby Isaac     v += spDim;
30927f02ce8SMatthew G. Knepley     /* TODO: For now, set both sides equal, but this should use info from other support cell */
3105fedec97SMatthew G. Knepley     if (isCohesive && !cohesive) {
31127f02ce8SMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = values[v - spDim];
31227f02ce8SMatthew G. Knepley     }
3138c6c5593SMatthew G. Knepley   }
314eb8f539aSJed Brown   if (localU) PetscCall(DMPlexVecRestoreClosure(dmIn, section, localU, inp, NULL, &coefficients));
3159566063dSJacob Faibussowitsch   if (dmAux) PetscCall(DMPlexVecRestoreClosure(dmAux, sectionAux, localA, p, NULL, &coefficientsAux));
3168e6d238bSMatthew G. Knepley   if (isCohesiveIn) PetscCall(DMPlexRestoreOrientedCone(dmIn, inp, &cone, &ornt));
3173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3188c6c5593SMatthew G. Knepley }
3198c6c5593SMatthew G. Knepley 
32079f2dbaeSMatthew G. Knepley static PetscErrorCode DMProjectPoint_BdField_Private(DM dm, PetscDS ds, DM dmIn, DMEnclosureType encIn, PetscDS dsIn, DM dmAux, DMEnclosureType encAux, PetscDS dsAux, PetscReal time, Vec localU, Vec localA, PetscFEGeom *fgeom, PetscDualSpace sp[], PetscInt p, PetscTabulation *T, PetscTabulation *TAux, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), void **ctxs, PetscScalar values[])
321d71ae5a4SJacob Faibussowitsch {
322b18799e0SMatthew G. Knepley   PetscSection       section, sectionAux = NULL;
3234bee2e38SMatthew G. Knepley   PetscScalar       *u, *u_t = NULL, *u_x, *a = NULL, *a_t = NULL, *a_x = NULL, *bc;
324b18799e0SMatthew G. Knepley   PetscScalar       *coefficients = NULL, *coefficientsAux = NULL;
325b18799e0SMatthew G. Knepley   PetscScalar       *coefficients_t = NULL, *coefficientsAux_t = NULL;
326b18799e0SMatthew G. Knepley   const PetscScalar *constants;
327b18799e0SMatthew G. Knepley   PetscReal         *x;
32879f2dbaeSMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nc, face[2];
3299f209ee4SMatthew G. Knepley   PetscFEGeom        fegeom, cgeom;
33079f2dbaeSMatthew G. Knepley   const PetscInt     dE = fgeom->dimEmbed, *cone, *ornt;
33179f2dbaeSMatthew G. Knepley   PetscInt           numConstants, Nf, NfIn, NfAux = 0, f, spDim, d, v, inp, tp = 0;
33279f2dbaeSMatthew G. Knepley   PetscBool          isAffine, isCohesive, isCohesiveIn, transform;
33379f2dbaeSMatthew G. Knepley   DMPolytopeType     qct;
334b18799e0SMatthew G. Knepley 
335b18799e0SMatthew G. Knepley   PetscFunctionBeginHot;
3369566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
3379566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
33879f2dbaeSMatthew G. Knepley   PetscCall(PetscDSIsCohesive(ds, &isCohesive));
33979f2dbaeSMatthew G. Knepley   PetscCall(PetscDSGetNumFields(dsIn, &NfIn));
34079f2dbaeSMatthew G. Knepley   PetscCall(PetscDSIsCohesive(dsIn, &isCohesiveIn));
34179f2dbaeSMatthew G. Knepley   PetscCall(PetscDSGetComponentOffsets(dsIn, &uOff));
34279f2dbaeSMatthew G. Knepley   PetscCall(PetscDSGetComponentDerivativeOffsets(dsIn, &uOff_x));
34379f2dbaeSMatthew G. Knepley   PetscCall(PetscDSGetEvaluationArrays(dsIn, &u, &bc /*&u_t*/, &u_x));
34479f2dbaeSMatthew G. Knepley   PetscCall(PetscDSGetWorkspace(dsIn, &x, NULL, NULL, NULL, NULL));
34579f2dbaeSMatthew G. Knepley   PetscCall(PetscDSGetConstants(dsIn, &numConstants, &constants));
34679f2dbaeSMatthew G. Knepley   PetscCall(DMHasBasisTransform(dmIn, &transform));
34779f2dbaeSMatthew G. Knepley   PetscCall(DMGetLocalSection(dmIn, &section));
34879f2dbaeSMatthew G. Knepley   PetscCall(DMGetEnclosurePoint(dmIn, dm, encIn, p, &inp));
34979f2dbaeSMatthew G. Knepley   // Get cohesive cell hanging off face
35079f2dbaeSMatthew G. Knepley   if (isCohesiveIn) {
35179f2dbaeSMatthew G. Knepley     PetscCall(DMPlexGetCellType(dmIn, inp, &qct));
35279f2dbaeSMatthew G. Knepley     if ((qct != DM_POLYTOPE_POINT_PRISM_TENSOR) && (qct != DM_POLYTOPE_SEG_PRISM_TENSOR) && (qct != DM_POLYTOPE_TRI_PRISM_TENSOR) && (qct != DM_POLYTOPE_QUAD_PRISM_TENSOR)) {
35379f2dbaeSMatthew G. Knepley       DMPolytopeType  ct;
35479f2dbaeSMatthew G. Knepley       const PetscInt *support;
35579f2dbaeSMatthew G. Knepley       PetscInt        Ns, s;
35679f2dbaeSMatthew G. Knepley 
35779f2dbaeSMatthew G. Knepley       PetscCall(DMPlexGetSupport(dmIn, inp, &support));
35879f2dbaeSMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dmIn, inp, &Ns));
35979f2dbaeSMatthew G. Knepley       for (s = 0; s < Ns; ++s) {
36079f2dbaeSMatthew G. Knepley         PetscCall(DMPlexGetCellType(dmIn, support[s], &ct));
36179f2dbaeSMatthew G. Knepley         if ((ct == DM_POLYTOPE_POINT_PRISM_TENSOR) || (ct == DM_POLYTOPE_SEG_PRISM_TENSOR) || (ct == DM_POLYTOPE_TRI_PRISM_TENSOR) || (ct == DM_POLYTOPE_QUAD_PRISM_TENSOR)) {
36279f2dbaeSMatthew G. Knepley           inp = support[s];
36379f2dbaeSMatthew G. Knepley           break;
36479f2dbaeSMatthew G. Knepley         }
36579f2dbaeSMatthew G. Knepley       }
36679f2dbaeSMatthew G. Knepley       PetscCheck(s < Ns, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cell not found from face %" PetscInt_FMT, inp);
36779f2dbaeSMatthew G. Knepley       PetscCall(PetscDSGetComponentOffsetsCohesive(dsIn, 2, &uOff));
36879f2dbaeSMatthew G. Knepley       PetscCall(DMPlexGetOrientedCone(dmIn, inp, &cone, &ornt));
36979f2dbaeSMatthew G. Knepley       face[0] = 0;
37079f2dbaeSMatthew G. Knepley       face[1] = 0;
37179f2dbaeSMatthew G. Knepley     }
37279f2dbaeSMatthew G. Knepley   }
37379f2dbaeSMatthew G. Knepley   if (localU) PetscCall(DMPlexVecGetClosure(dmIn, section, localU, inp, NULL, &coefficients));
374b18799e0SMatthew G. Knepley   if (dmAux) {
375a6e0b375SMatthew G. Knepley     PetscInt subp;
376b18799e0SMatthew G. Knepley 
3779566063dSJacob Faibussowitsch     PetscCall(DMGetEnclosurePoint(dmAux, dm, encAux, p, &subp));
3789566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(dsAux, &NfAux));
3799566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dmAux, &sectionAux));
3809566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff));
3819566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x));
3829566063dSJacob Faibussowitsch     PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL /*&a_t*/, &a_x));
3839566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmAux, sectionAux, localA, subp, NULL, &coefficientsAux));
384b18799e0SMatthew G. Knepley   }
385b18799e0SMatthew G. Knepley   /* Get values for closure */
3864bee2e38SMatthew G. Knepley   isAffine       = fgeom->isAffine;
387ea78f98cSLisandro Dalcin   fegeom.n       = NULL;
388ea78f98cSLisandro Dalcin   fegeom.J       = NULL;
389ea78f98cSLisandro Dalcin   fegeom.v       = NULL;
390ea78f98cSLisandro Dalcin   fegeom.xi      = NULL;
391a6e0b375SMatthew G. Knepley   cgeom.dim      = fgeom->dim;
392a6e0b375SMatthew G. Knepley   cgeom.dimEmbed = fgeom->dimEmbed;
3934bee2e38SMatthew G. Knepley   if (isAffine) {
3944bee2e38SMatthew G. Knepley     fegeom.v    = x;
3954bee2e38SMatthew G. Knepley     fegeom.xi   = fgeom->xi;
3964bee2e38SMatthew G. Knepley     fegeom.J    = fgeom->J;
3974bee2e38SMatthew G. Knepley     fegeom.invJ = fgeom->invJ;
3984bee2e38SMatthew G. Knepley     fegeom.detJ = fgeom->detJ;
3994bee2e38SMatthew G. Knepley     fegeom.n    = fgeom->n;
4009f209ee4SMatthew G. Knepley 
4019f209ee4SMatthew G. Knepley     cgeom.J    = fgeom->suppJ[0];
4029f209ee4SMatthew G. Knepley     cgeom.invJ = fgeom->suppInvJ[0];
4039f209ee4SMatthew G. Knepley     cgeom.detJ = fgeom->suppDetJ[0];
4044bee2e38SMatthew G. Knepley   }
405b18799e0SMatthew G. Knepley   for (f = 0, v = 0; f < Nf; ++f) {
406b18799e0SMatthew G. Knepley     PetscQuadrature  allPoints;
407b18799e0SMatthew G. Knepley     PetscInt         q, dim, numPoints;
408b18799e0SMatthew G. Knepley     const PetscReal *points;
409b18799e0SMatthew G. Knepley     PetscScalar     *pointEval;
41079f2dbaeSMatthew G. Knepley     PetscBool        cohesive;
411b18799e0SMatthew G. Knepley     DM               dm;
412b18799e0SMatthew G. Knepley 
413b18799e0SMatthew G. Knepley     if (!sp[f]) continue;
41479f2dbaeSMatthew G. Knepley     PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
4159566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDimension(sp[f], &spDim));
416b18799e0SMatthew G. Knepley     if (!funcs[f]) {
417b18799e0SMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = 0.;
41879f2dbaeSMatthew G. Knepley       if (isCohesive && !cohesive) {
41979f2dbaeSMatthew G. Knepley         for (d = 0; d < spDim; d++, v++) values[v] = 0.;
42079f2dbaeSMatthew G. Knepley       }
421b18799e0SMatthew G. Knepley       continue;
422b18799e0SMatthew G. Knepley     }
4239566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDM(sp[f], &dm));
4249566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL));
4259566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(allPoints, &dim, NULL, &numPoints, &points, NULL));
4269566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
427b18799e0SMatthew G. Knepley     for (q = 0; q < numPoints; ++q, ++tp) {
42879f2dbaeSMatthew G. Knepley       PetscInt qpt[2];
42979f2dbaeSMatthew G. Knepley 
43079f2dbaeSMatthew G. Knepley       if (isCohesiveIn) {
43179f2dbaeSMatthew G. Knepley         // These points are not integration quadratures, but dual space quadratures
432d8b4a066SPierre Jolivet         // If they had multiple points we should match them from both sides, similar to hybrid residual eval
43379f2dbaeSMatthew G. Knepley         qpt[0] = qpt[1] = q;
43479f2dbaeSMatthew G. Knepley       }
435b18799e0SMatthew G. Knepley       if (isAffine) {
436ef0bb6c7SMatthew G. Knepley         CoordinatesRefToReal(dE, fgeom->dim, fegeom.xi, fgeom->v, fegeom.J, &points[q * dim], x);
437b18799e0SMatthew G. Knepley       } else {
4383fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[tp * dE];
4399f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[tp * dE * dE];
4409f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[tp * dE * dE];
4414bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[tp];
4424bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[tp * dE];
4439f209ee4SMatthew G. Knepley 
4449f209ee4SMatthew G. Knepley         cgeom.J    = &fgeom->suppJ[0][tp * dE * dE];
4459f209ee4SMatthew G. Knepley         cgeom.invJ = &fgeom->suppInvJ[0][tp * dE * dE];
4469f209ee4SMatthew G. Knepley         cgeom.detJ = &fgeom->suppDetJ[0][tp];
447b18799e0SMatthew G. Knepley       }
448a6e0b375SMatthew G. Knepley       /* TODO We should use cgeom here, instead of fegeom, however the geometry coming in through fgeom does not have the support cell geometry */
44979f2dbaeSMatthew G. Knepley       if (coefficients) {
45079f2dbaeSMatthew G. Knepley         if (isCohesiveIn) PetscCall(PetscFEEvaluateFieldJets_Hybrid_Internal(dsIn, NfIn, 0, tp, T, face, qpt, T, &cgeom, coefficients, coefficients_t, u, u_x, u_t));
45179f2dbaeSMatthew G. Knepley         else PetscCall(PetscFEEvaluateFieldJets_Internal(dsIn, NfIn, 0, tp, T, &cgeom, coefficients, coefficients_t, u, u_x, u_t));
45279f2dbaeSMatthew G. Knepley       }
4539566063dSJacob Faibussowitsch       if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, tp, TAux, &cgeom, coefficientsAux, coefficientsAux_t, a, a_x, a_t));
45479f2dbaeSMatthew G. Knepley       if (transform) PetscCall(DMPlexBasisTransformApplyReal_Internal(dmIn, fegeom.v, PETSC_TRUE, dE, fegeom.v, fegeom.v, dm->transformCtx));
45579f2dbaeSMatthew G. Knepley       (*funcs[f])(dE, NfIn, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, time, fegeom.v, fegeom.n, numConstants, constants, &pointEval[Nc[f] * q]);
456b18799e0SMatthew G. Knepley     }
4579566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v]));
4589566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
459b18799e0SMatthew G. Knepley     v += spDim;
46079f2dbaeSMatthew G. Knepley     /* TODO: For now, set both sides equal, but this should use info from other support cell */
46179f2dbaeSMatthew G. Knepley     if (isCohesive && !cohesive) {
46279f2dbaeSMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = values[v - spDim];
463b18799e0SMatthew G. Knepley     }
46479f2dbaeSMatthew G. Knepley   }
46579f2dbaeSMatthew G. Knepley   if (localU) PetscCall(DMPlexVecRestoreClosure(dmIn, section, localU, inp, NULL, &coefficients));
4669566063dSJacob Faibussowitsch   if (dmAux) PetscCall(DMPlexVecRestoreClosure(dmAux, sectionAux, localA, p, NULL, &coefficientsAux));
46779f2dbaeSMatthew G. Knepley   if (isCohesiveIn) PetscCall(DMPlexRestoreOrientedCone(dmIn, inp, &cone, &ornt));
4683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
469b18799e0SMatthew G. Knepley }
470b18799e0SMatthew G. Knepley 
471d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectPoint_Private(DM dm, PetscDS ds, DM dmIn, DMEnclosureType encIn, PetscDS dsIn, DM dmAux, DMEnclosureType encAux, PetscDS dsAux, PetscFEGeom *fegeom, PetscInt effectiveHeight, PetscReal time, Vec localU, Vec localA, PetscBool hasFE, PetscBool hasFV, PetscBool isFE[], PetscDualSpace sp[], PetscInt p, PetscTabulation *T, PetscTabulation *TAux, DMBoundaryConditionType type, void (**funcs)(void), void **ctxs, PetscBool fieldActive[], PetscScalar values[])
472d71ae5a4SJacob Faibussowitsch {
4738c6c5593SMatthew G. Knepley   PetscFVCellGeom fvgeom;
4748c6c5593SMatthew G. Knepley   PetscInt        dim, dimEmbed;
4758c6c5593SMatthew G. Knepley 
4768c6c5593SMatthew G. Knepley   PetscFunctionBeginHot;
4779566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
4789566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
4799566063dSJacob Faibussowitsch   if (hasFV) PetscCall(DMPlexComputeCellGeometryFVM(dm, p, &fvgeom.volume, fvgeom.centroid, NULL));
4808c6c5593SMatthew G. Knepley   switch (type) {
4818c6c5593SMatthew G. Knepley   case DM_BC_ESSENTIAL:
482d71ae5a4SJacob Faibussowitsch   case DM_BC_NATURAL:
483d71ae5a4SJacob Faibussowitsch     PetscCall(DMProjectPoint_Func_Private(dm, ds, dmIn, dsIn, time, fegeom, &fvgeom, isFE, sp, (PetscErrorCode(**)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *))funcs, ctxs, values));
484d71ae5a4SJacob Faibussowitsch     break;
4858c6c5593SMatthew G. Knepley   case DM_BC_ESSENTIAL_FIELD:
4868c6c5593SMatthew G. Knepley   case DM_BC_NATURAL_FIELD:
4879371c9d4SSatish Balay     PetscCall(DMProjectPoint_Field_Private(dm, ds, dmIn, encIn, dsIn, dmAux, encAux, dsAux, time, localU, localA, fegeom, sp, p, T, TAux, (void (**)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]))funcs, ctxs, values));
488d0609cedSBarry Smith     break;
489b18799e0SMatthew G. Knepley   case DM_BC_ESSENTIAL_BD_FIELD:
49079f2dbaeSMatthew G. Knepley     PetscCall(DMProjectPoint_BdField_Private(dm, ds, dmIn, encIn, dsIn, dmAux, encAux, dsAux, time, localU, localA, fegeom, sp, p, T, TAux, (void (**)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]))funcs, ctxs, values));
491d0609cedSBarry Smith     break;
492d71ae5a4SJacob Faibussowitsch   default:
493d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown boundary condition type: %d", (int)type);
4948c6c5593SMatthew G. Knepley   }
4953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4968c6c5593SMatthew G. Knepley }
4978c6c5593SMatthew G. Knepley 
498d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceGetAllPointsUnion(PetscInt Nf, PetscDualSpace *sp, PetscInt dim, void (**funcs)(void), PetscQuadrature *allPoints)
499d71ae5a4SJacob Faibussowitsch {
500df5c1128SToby Isaac   PetscReal *points;
501df5c1128SToby Isaac   PetscInt   f, numPoints;
502df5c1128SToby Isaac 
503df5c1128SToby Isaac   PetscFunctionBegin;
50419552267SMatthew G. Knepley   if (!dim) {
50519552267SMatthew G. Knepley     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allPoints));
5063ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
50719552267SMatthew G. Knepley   }
508df5c1128SToby Isaac   numPoints = 0;
509df5c1128SToby Isaac   for (f = 0; f < Nf; ++f) {
510df5c1128SToby Isaac     if (funcs[f]) {
511df5c1128SToby Isaac       PetscQuadrature fAllPoints;
512df5c1128SToby Isaac       PetscInt        fNumPoints;
513df5c1128SToby Isaac 
5149566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceGetAllData(sp[f], &fAllPoints, NULL));
5159566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureGetData(fAllPoints, NULL, NULL, &fNumPoints, NULL, NULL));
516df5c1128SToby Isaac       numPoints += fNumPoints;
517df5c1128SToby Isaac     }
518df5c1128SToby Isaac   }
5199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dim * numPoints, &points));
520df5c1128SToby Isaac   numPoints = 0;
521df5c1128SToby Isaac   for (f = 0; f < Nf; ++f) {
522df5c1128SToby Isaac     if (funcs[f]) {
523df5c1128SToby Isaac       PetscQuadrature  fAllPoints;
52454ee0cceSMatthew G. Knepley       PetscInt         qdim, fNumPoints, q;
525df5c1128SToby Isaac       const PetscReal *fPoints;
526df5c1128SToby Isaac 
5279566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceGetAllData(sp[f], &fAllPoints, NULL));
5289566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureGetData(fAllPoints, &qdim, NULL, &fNumPoints, &fPoints, NULL));
52963a3b9bcSJacob Faibussowitsch       PetscCheck(qdim == dim, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Spatial dimension %" PetscInt_FMT " for dual basis does not match input dimension %" PetscInt_FMT, qdim, dim);
530df5c1128SToby Isaac       for (q = 0; q < fNumPoints * dim; ++q) points[numPoints * dim + q] = fPoints[q];
531df5c1128SToby Isaac       numPoints += fNumPoints;
532df5c1128SToby Isaac     }
533df5c1128SToby Isaac   }
5349566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allPoints));
5359566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureSetData(*allPoints, dim, 0, numPoints, points, NULL));
5363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
537df5c1128SToby Isaac }
538df5c1128SToby Isaac 
5395f15299fSJeremy L Thompson /*@C
54020f4b53cSBarry Smith   DMGetFirstLabeledPoint - Find first labeled `point` in `odm` such that the corresponding point in `dm` has the specified `height`. Return `point` and the corresponding `ds`.
5415f15299fSJeremy L Thompson 
5425f15299fSJeremy L Thompson   Input Parameters:
5432fe279fdSBarry Smith + dm     - the `DM`
5442fe279fdSBarry Smith . odm    - the enclosing `DM`
5452fe279fdSBarry Smith . label  - label for `DM` domain, or `NULL` for whole domain
5462fe279fdSBarry Smith . numIds - the number of `ids`
5472fe279fdSBarry Smith . ids    - An array of the label ids in sequence for the domain
5482fe279fdSBarry Smith - height - Height of target cells in `DMPLEX` topology
5495f15299fSJeremy L Thompson 
5505f15299fSJeremy L Thompson   Output Parameters:
5512fe279fdSBarry Smith + point - the first labeled point
552a3b724e8SBarry Smith - ds    - the `PetscDS` corresponding to the first labeled point
5535f15299fSJeremy L Thompson 
5545f15299fSJeremy L Thompson   Level: developer
555a1cb98faSBarry Smith 
5561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetActivePoint()`, `DMLabel`, `PetscDS`
557817da375SSatish Balay @*/
558d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFirstLabeledPoint(DM dm, DM odm, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt height, PetscInt *point, PetscDS *ds)
559d71ae5a4SJacob Faibussowitsch {
560a6e0b375SMatthew G. Knepley   DM              plex;
561a6e0b375SMatthew G. Knepley   DMEnclosureType enc;
562e9f0ba4eSJed Brown   PetscInt        ls = -1;
563e5e52638SMatthew G. Knepley 
564e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5655f15299fSJeremy L Thompson   if (point) *point = -1;
5663ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
5679566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosureRelation(dm, odm, &enc));
5689566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
569e9f0ba4eSJed Brown   for (PetscInt i = 0; i < numIds; ++i) {
570e9f0ba4eSJed Brown     IS       labelIS;
571e9f0ba4eSJed Brown     PetscInt num_points, pStart, pEnd;
5729566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, ids[i], &labelIS));
573e9f0ba4eSJed Brown     if (!labelIS) continue; /* No points with that id on this process */
5749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(plex, height, &pStart, &pEnd));
5759566063dSJacob Faibussowitsch     PetscCall(ISGetSize(labelIS, &num_points));
576e9f0ba4eSJed Brown     if (num_points) {
577e5e52638SMatthew G. Knepley       const PetscInt *points;
5789566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(labelIS, &points));
579e9f0ba4eSJed Brown       for (PetscInt i = 0; i < num_points; i++) {
580e9f0ba4eSJed Brown         PetscInt point;
5819566063dSJacob Faibussowitsch         PetscCall(DMGetEnclosurePoint(dm, odm, enc, points[i], &point));
582e9f0ba4eSJed Brown         if (pStart <= point && point < pEnd) {
583a6e0b375SMatthew G. Knepley           ls = point;
58479f2dbaeSMatthew G. Knepley           if (ds) {
58579f2dbaeSMatthew G. Knepley             // If this is a face of a cohesive cell, then prefer that DS
58679f2dbaeSMatthew G. Knepley             if (height == 1) {
58779f2dbaeSMatthew G. Knepley               const PetscInt *supp;
58879f2dbaeSMatthew G. Knepley               PetscInt        suppSize;
58979f2dbaeSMatthew G. Knepley               DMPolytopeType  ct;
59079f2dbaeSMatthew G. Knepley 
59179f2dbaeSMatthew G. Knepley               PetscCall(DMPlexGetSupport(dm, ls, &supp));
59279f2dbaeSMatthew G. Knepley               PetscCall(DMPlexGetSupportSize(dm, ls, &suppSize));
59379f2dbaeSMatthew G. Knepley               for (PetscInt s = 0; s < suppSize; ++s) {
59479f2dbaeSMatthew G. Knepley                 PetscCall(DMPlexGetCellType(dm, supp[s], &ct));
59579f2dbaeSMatthew G. Knepley                 if ((ct == DM_POLYTOPE_POINT_PRISM_TENSOR) || (ct == DM_POLYTOPE_SEG_PRISM_TENSOR) || (ct == DM_POLYTOPE_TRI_PRISM_TENSOR) || (ct == DM_POLYTOPE_QUAD_PRISM_TENSOR)) {
59679f2dbaeSMatthew G. Knepley                   ls = supp[s];
59779f2dbaeSMatthew G. Knepley                   break;
59879f2dbaeSMatthew G. Knepley                 }
59979f2dbaeSMatthew G. Knepley               }
60079f2dbaeSMatthew G. Knepley             }
60179f2dbaeSMatthew G. Knepley             PetscCall(DMGetCellDS(dm, ls, ds, NULL));
60279f2dbaeSMatthew G. Knepley           }
6038e6d238bSMatthew G. Knepley           if (ls >= 0) break;
604e5e52638SMatthew G. Knepley         }
605e9f0ba4eSJed Brown       }
6069566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(labelIS, &points));
607e9f0ba4eSJed Brown     }
6089566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&labelIS));
609e5e52638SMatthew G. Knepley     if (ls >= 0) break;
610e5e52638SMatthew G. Knepley   }
6115f15299fSJeremy L Thompson   if (point) *point = ls;
6129566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
6133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
614e5e52638SMatthew G. Knepley }
615e5e52638SMatthew G. Knepley 
6160de51b56SMatthew G. Knepley /*
6170de51b56SMatthew G. Knepley   This function iterates over a manifold, and interpolates the input function/field using the basis provided by the DS in our DM
6180de51b56SMatthew G. Knepley 
6190de51b56SMatthew G. Knepley   There are several different scenarios:
6200de51b56SMatthew G. Knepley 
6210de51b56SMatthew G. Knepley   1) Volumetric mesh with volumetric auxiliary data
6220de51b56SMatthew G. Knepley 
6230de51b56SMatthew G. Knepley      Here minHeight=0 since we loop over cells.
6240de51b56SMatthew G. Knepley 
6250de51b56SMatthew G. Knepley   2) Boundary mesh with boundary auxiliary data
6260de51b56SMatthew G. Knepley 
6270de51b56SMatthew G. Knepley      Here minHeight=1 since we loop over faces. This normally happens since we hang cells off of our boundary meshes to facilitate computation.
6280de51b56SMatthew G. Knepley 
6290de51b56SMatthew G. Knepley   3) Volumetric mesh with boundary auxiliary data
6300de51b56SMatthew G. Knepley 
6310de51b56SMatthew G. Knepley      Here minHeight=1 and auxbd=PETSC_TRUE since we loop over faces and use data only supported on those faces. This is common when imposing Dirichlet boundary conditions.
6320de51b56SMatthew G. Knepley 
633636b9322SMatthew G. Knepley   4) Volumetric input mesh with boundary output mesh
634636b9322SMatthew G. Knepley 
635636b9322SMatthew G. Knepley      Here we must get a subspace for the input DS
636636b9322SMatthew G. Knepley 
6370de51b56SMatthew G. Knepley   The maxHeight is used to support enforcement of constraints in DMForest.
6380de51b56SMatthew G. Knepley 
6390de51b56SMatthew G. Knepley   If localU is given and not equal to localX, we call DMPlexInsertBoundaryValues() to complete it.
6400de51b56SMatthew G. Knepley 
6410de51b56SMatthew G. Knepley   If we are using an input field (DM_BC_ESSENTIAL_FIELD or DM_BC_NATURAL_FIELD), we need to evaluate it at all the quadrature points of the dual basis functionals.
6420de51b56SMatthew G. Knepley     - We use effectiveHeight to mean the height above our incoming DS. For example, if the DS is for a submesh then the effective height is zero, whereas if the DS
6435f790a90SMatthew G. Knepley       is for the volumetric mesh, but we are iterating over a surface, then the effective height is nonzero. When the effective height is nonzero, we need to extract
6440de51b56SMatthew G. Knepley       dual spaces for the boundary from our input spaces.
6450de51b56SMatthew G. Knepley     - After extracting all quadrature points, we tabulate the input fields and auxiliary fields on them.
6460de51b56SMatthew G. Knepley 
6470de51b56SMatthew G. Knepley   We check that the #dof(closure(p)) == #dual basis functionals(p) for a representative p in the iteration
6480de51b56SMatthew G. Knepley 
6490de51b56SMatthew G. Knepley   If we have a label, we iterate over those points. This will probably break the maxHeight functionality since we do not check the height of those points.
6500de51b56SMatthew G. Knepley */
651d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectLocal_Generic_Plex(DM dm, PetscReal time, Vec localU, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt numIds, const PetscInt ids[], DMBoundaryConditionType type, void (**funcs)(void), void **ctxs, InsertMode mode, Vec localX)
652d71ae5a4SJacob Faibussowitsch {
653a6e0b375SMatthew G. Knepley   DM               plex, dmIn, plexIn, dmAux = NULL, plexAux = NULL, tdm;
654a6e0b375SMatthew G. Knepley   DMEnclosureType  encIn, encAux;
655a6e0b375SMatthew G. Knepley   PetscDS          ds = NULL, dsIn = NULL, dsAux = NULL;
656ca3d3a14SMatthew G. Knepley   Vec              localA = NULL, tv;
657aa0eca99SMatthew G. Knepley   IS               fieldIS;
65847923291SMatthew G. Knepley   PetscSection     section;
659636b9322SMatthew G. Knepley   PetscDualSpace  *sp, *cellsp, *spIn, *cellspIn;
660ef0bb6c7SMatthew G. Knepley   PetscTabulation *T = NULL, *TAux = NULL;
6618c6c5593SMatthew G. Knepley   PetscInt        *Nc;
66279f2dbaeSMatthew G. Knepley   PetscInt         dim, dimEmbed, depth, htInc = 0, htIncIn = 0, htIncAux = 0, minHeight, maxHeight, minHeightIn, minHeightAux, h, regionNum, Nf, NfIn, NfAux = 0, NfTot, f;
6638e6d238bSMatthew G. Knepley   PetscBool       *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE, isCohesive = PETSC_FALSE, isCohesiveIn = PETSC_FALSE, transform;
664c330f8ffSToby Isaac   DMField          coordField;
665c330f8ffSToby Isaac   DMLabel          depthLabel;
666c330f8ffSToby Isaac   PetscQuadrature  allPoints = NULL;
66747923291SMatthew G. Knepley 
66847923291SMatthew G. Knepley   PetscFunctionBegin;
6699566063dSJacob Faibussowitsch   if (localU) PetscCall(VecGetDM(localU, &dmIn));
670ad540459SPierre Jolivet   else dmIn = dm;
6719566063dSJacob Faibussowitsch   PetscCall(DMGetAuxiliaryVec(dm, label, numIds ? ids[0] : 0, 0, &localA));
6729371c9d4SSatish Balay   if (localA) PetscCall(VecGetDM(localA, &dmAux));
673ad540459SPierre Jolivet   else dmAux = NULL;
6749566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
6759566063dSJacob Faibussowitsch   PetscCall(DMConvert(dmIn, DMPLEX, &plexIn));
6769566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosureRelation(dmIn, dm, &encIn));
6779566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
6789566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
6799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(plex, &minHeight));
6809566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
6819566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
6829566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dm, &transform));
6830de51b56SMatthew G. Knepley   /* Auxiliary information can only be used with interpolation of field functions */
684a6e0b375SMatthew G. Knepley   if (dmAux) {
6859566063dSJacob Faibussowitsch     PetscCall(DMConvert(dmAux, DMPLEX, &plexAux));
686ad540459SPierre Jolivet     if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) PetscCheck(localA, PETSC_COMM_SELF, PETSC_ERR_USER, "Missing localA vector");
687636b9322SMatthew G. Knepley   }
6885ee220baSJed Brown   if (localU && localU != localX) PetscCall(DMPlexInsertBoundaryValues(plexIn, PETSC_TRUE, localU, time, NULL, NULL, NULL));
689e04ae0b4SMatthew G. Knepley   PetscCall(DMGetCoordinateField(dm, &coordField));
690e44f6aebSMatthew G. Knepley   PetscCheck(coordField, PETSC_COMM_SELF, PETSC_ERR_USER, "DM must have a coordinate field");
691e04ae0b4SMatthew G. Knepley   /**** No collective calls below this point ****/
692636b9322SMatthew G. Knepley   /* Determine height for iteration of all meshes */
693636b9322SMatthew G. Knepley   {
694636b9322SMatthew G. Knepley     DMPolytopeType ct, ctIn, ctAux;
69579f2dbaeSMatthew G. Knepley     PetscInt       lStart, pStart, pEnd, p, pStartIn, pStartAux, pEndAux;
69619552267SMatthew G. Knepley     PetscInt       dim = -1, dimIn = -1, dimAux = -1;
69788aca1feSMatthew G. Knepley 
6989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSimplexOrBoxCells(plex, minHeight, &pStart, &pEnd));
699636b9322SMatthew G. Knepley     if (pEnd > pStart) {
7009566063dSJacob Faibussowitsch       PetscCall(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, minHeight, &lStart, NULL));
701636b9322SMatthew G. Knepley       p = lStart < 0 ? pStart : lStart;
7029566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(plex, p, &ct));
703636b9322SMatthew G. Knepley       dim = DMPolytopeTypeGetDim(ct);
7049566063dSJacob Faibussowitsch       PetscCall(DMPlexGetVTKCellHeight(plexIn, &minHeightIn));
7059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSimplexOrBoxCells(plexIn, minHeightIn, &pStartIn, NULL));
7069566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(plexIn, pStartIn, &ctIn));
707636b9322SMatthew G. Knepley       dimIn = DMPolytopeTypeGetDim(ctIn);
708636b9322SMatthew G. Knepley       if (dmAux) {
7099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetVTKCellHeight(plexAux, &minHeightAux));
71019552267SMatthew G. Knepley         PetscCall(DMPlexGetSimplexOrBoxCells(plexAux, minHeightAux, &pStartAux, &pEndAux));
71119552267SMatthew G. Knepley         if (pStartAux < pEndAux) {
7129566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(plexAux, pStartAux, &ctAux));
713636b9322SMatthew G. Knepley           dimAux = DMPolytopeTypeGetDim(ctAux);
71419552267SMatthew G. Knepley         }
715636b9322SMatthew G. Knepley       } else dimAux = dim;
716e04ae0b4SMatthew G. Knepley     } else {
717e04ae0b4SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
718e04ae0b4SMatthew G. Knepley       PetscCall(DMDestroy(&plexIn));
719e04ae0b4SMatthew G. Knepley       if (dmAux) PetscCall(DMDestroy(&plexAux));
7203ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
721e39fcb4eSStefano Zampini     }
722636b9322SMatthew G. Knepley     if (dim < 0) {
723636b9322SMatthew G. Knepley       DMLabel spmap = NULL, spmapIn = NULL, spmapAux = NULL;
724636b9322SMatthew G. Knepley 
725636b9322SMatthew G. Knepley       /* Fall back to determination based on being a submesh */
7269566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSubpointMap(plex, &spmap));
7279566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSubpointMap(plexIn, &spmapIn));
7289566063dSJacob Faibussowitsch       if (plexAux) PetscCall(DMPlexGetSubpointMap(plexAux, &spmapAux));
729636b9322SMatthew G. Knepley       dim    = spmap ? 1 : 0;
730636b9322SMatthew G. Knepley       dimIn  = spmapIn ? 1 : 0;
731636b9322SMatthew G. Knepley       dimAux = spmapAux ? 1 : 0;
73288aca1feSMatthew G. Knepley     }
733636b9322SMatthew G. Knepley     {
734*57508eceSPierre Jolivet       PetscInt dimProj   = PetscMin(PetscMin(dim, dimIn), dimAux < 0 ? PETSC_INT_MAX : dimAux);
73519552267SMatthew G. Knepley       PetscInt dimAuxEff = dimAux < 0 ? dimProj : dimAux;
736636b9322SMatthew G. Knepley 
73719552267SMatthew G. Knepley       PetscCheck(PetscAbsInt(dimProj - dim) <= 1 && PetscAbsInt(dimProj - dimIn) <= 1 && PetscAbsInt(dimProj - dimAuxEff) <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not currently support differences of more than 1 in dimension");
738636b9322SMatthew G. Knepley       if (dimProj < dim) minHeight = 1;
739636b9322SMatthew G. Knepley       htInc    = dim - dimProj;
740636b9322SMatthew G. Knepley       htIncIn  = dimIn - dimProj;
74119552267SMatthew G. Knepley       htIncAux = dimAuxEff - dimProj;
7420de51b56SMatthew G. Knepley     }
743a6e0b375SMatthew G. Knepley   }
7449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(plex, &depth));
7459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(plex, &depthLabel));
7469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(plex, &maxHeight));
7472af58022SMatthew G. Knepley   maxHeight = PetscMax(maxHeight, minHeight);
74863a3b9bcSJacob Faibussowitsch   PetscCheck(maxHeight >= 0 && maxHeight <= dim, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Maximum projection height %" PetscInt_FMT " not in [0, %" PetscInt_FMT ")", maxHeight, dim);
74979f2dbaeSMatthew G. Knepley   PetscCall(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, minHeight, NULL, &ds));
7509566063dSJacob Faibussowitsch   if (!ds) PetscCall(DMGetDS(dm, &ds));
75179f2dbaeSMatthew G. Knepley   PetscCall(DMGetFirstLabeledPoint(dmIn, dm, label, numIds, ids, minHeight, NULL, &dsIn));
7529566063dSJacob Faibussowitsch   if (!dsIn) PetscCall(DMGetDS(dmIn, &dsIn));
7539566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
7549566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(dsIn, &NfIn));
7558e6d238bSMatthew G. Knepley   PetscCall(PetscDSIsCohesive(dsIn, &isCohesiveIn));
7568e6d238bSMatthew G. Knepley   if (isCohesiveIn) --htIncIn; // Should be rearranged
7579566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &NfTot));
7589566063dSJacob Faibussowitsch   PetscCall(DMFindRegionNum(dm, ds, &regionNum));
75907218a29SMatthew G. Knepley   PetscCall(DMGetRegionNumDS(dm, regionNum, NULL, &fieldIS, NULL, NULL));
7609566063dSJacob Faibussowitsch   PetscCall(PetscDSIsCohesive(ds, &isCohesive));
7619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
7629566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
7630c898c18SMatthew G. Knepley   if (dmAux) {
7649566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmAux, &dsAux));
7659566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(dsAux, &NfAux));
7660c898c18SMatthew G. Knepley   }
7679566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
7689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(Nf, &isFE, Nf, &sp, NfIn, &spIn));
7699566063dSJacob Faibussowitsch   if (maxHeight > 0) PetscCall(PetscMalloc2(Nf, &cellsp, NfIn, &cellspIn));
7709371c9d4SSatish Balay   else {
7719371c9d4SSatish Balay     cellsp   = sp;
7729371c9d4SSatish Balay     cellspIn = spIn;
7739371c9d4SSatish Balay   }
7748c6c5593SMatthew G. Knepley   /* Get cell dual spaces */
77547923291SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
776665f567fSMatthew G. Knepley     PetscDiscType disctype;
77747923291SMatthew G. Knepley 
7789566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscType_Internal(ds, f, &disctype));
779665f567fSMatthew G. Knepley     if (disctype == PETSC_DISC_FE) {
780665f567fSMatthew G. Knepley       PetscFE fe;
78147923291SMatthew G. Knepley 
78247923291SMatthew G. Knepley       isFE[f] = PETSC_TRUE;
783665f567fSMatthew G. Knepley       hasFE   = PETSC_TRUE;
7849566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, (PetscObject *)&fe));
7859566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace(fe, &cellsp[f]));
786665f567fSMatthew G. Knepley     } else if (disctype == PETSC_DISC_FV) {
787665f567fSMatthew G. Knepley       PetscFV fv;
78847923291SMatthew G. Knepley 
78947923291SMatthew G. Knepley       isFE[f] = PETSC_FALSE;
790665f567fSMatthew G. Knepley       hasFV   = PETSC_TRUE;
7919566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, (PetscObject *)&fv));
7929566063dSJacob Faibussowitsch       PetscCall(PetscFVGetDualSpace(fv, &cellsp[f]));
793665f567fSMatthew G. Knepley     } else {
794665f567fSMatthew G. Knepley       isFE[f]   = PETSC_FALSE;
795665f567fSMatthew G. Knepley       cellsp[f] = NULL;
796665f567fSMatthew G. Knepley     }
79747923291SMatthew G. Knepley   }
798636b9322SMatthew G. Knepley   for (f = 0; f < NfIn; ++f) {
799636b9322SMatthew G. Knepley     PetscDiscType disctype;
800636b9322SMatthew G. Knepley 
8019566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscType_Internal(dsIn, f, &disctype));
802636b9322SMatthew G. Knepley     if (disctype == PETSC_DISC_FE) {
803636b9322SMatthew G. Knepley       PetscFE fe;
804636b9322SMatthew G. Knepley 
8059566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsIn, f, (PetscObject *)&fe));
8069566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace(fe, &cellspIn[f]));
807636b9322SMatthew G. Knepley     } else if (disctype == PETSC_DISC_FV) {
808636b9322SMatthew G. Knepley       PetscFV fv;
809636b9322SMatthew G. Knepley 
8109566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsIn, f, (PetscObject *)&fv));
8119566063dSJacob Faibussowitsch       PetscCall(PetscFVGetDualSpace(fv, &cellspIn[f]));
812636b9322SMatthew G. Knepley     } else {
813636b9322SMatthew G. Knepley       cellspIn[f] = NULL;
814636b9322SMatthew G. Knepley     }
815636b9322SMatthew G. Knepley   }
816636b9322SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
8179371c9d4SSatish Balay     if (!htInc) {
8189371c9d4SSatish Balay       sp[f] = cellsp[f];
8199371c9d4SSatish Balay     } else PetscCall(PetscDualSpaceGetHeightSubspace(cellsp[f], htInc, &sp[f]));
820636b9322SMatthew G. Knepley   }
821ece3a9fcSMatthew G. Knepley   if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) {
82274fc349aSMatthew G. Knepley     PetscFE          fem, subfem;
823665f567fSMatthew G. Knepley     PetscDiscType    disctype;
8244a3e9fdbSToby Isaac     const PetscReal *points;
8254a3e9fdbSToby Isaac     PetscInt         numPoints;
8260c898c18SMatthew G. Knepley 
82708401ef6SPierre Jolivet     PetscCheck(maxHeight <= minHeight, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Field projection not supported for face interpolation");
8289566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetAllPointsUnion(Nf, sp, dim - htInc, funcs, &allPoints));
8299566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(allPoints, NULL, NULL, &numPoints, &points, NULL));
8309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(NfIn, &T, NfAux, &TAux));
831a6e0b375SMatthew G. Knepley     for (f = 0; f < NfIn; ++f) {
8329371c9d4SSatish Balay       if (!htIncIn) {
8339371c9d4SSatish Balay         spIn[f] = cellspIn[f];
8349371c9d4SSatish Balay       } else PetscCall(PetscDualSpaceGetHeightSubspace(cellspIn[f], htIncIn, &spIn[f]));
835636b9322SMatthew G. Knepley 
8369566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscType_Internal(dsIn, f, &disctype));
837665f567fSMatthew G. Knepley       if (disctype != PETSC_DISC_FE) continue;
8389566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsIn, f, (PetscObject *)&fem));
8399371c9d4SSatish Balay       if (!htIncIn) {
8409371c9d4SSatish Balay         subfem = fem;
8419371c9d4SSatish Balay       } else PetscCall(PetscFEGetHeightSubspace(fem, htIncIn, &subfem));
8429566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &T[f]));
8430c898c18SMatthew G. Knepley     }
8440c898c18SMatthew G. Knepley     for (f = 0; f < NfAux; ++f) {
8459566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscType_Internal(dsAux, f, &disctype));
846665f567fSMatthew G. Knepley       if (disctype != PETSC_DISC_FE) continue;
8479566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsAux, f, (PetscObject *)&fem));
8489371c9d4SSatish Balay       if (!htIncAux) {
8499371c9d4SSatish Balay         subfem = fem;
8509371c9d4SSatish Balay       } else PetscCall(PetscFEGetHeightSubspace(fem, htIncAux, &subfem));
8519566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &TAux[f]));
8520c898c18SMatthew G. Knepley     }
8530c898c18SMatthew G. Knepley   }
85447923291SMatthew G. Knepley   /* Note: We make no attempt to optimize for height. Higher height things just overwrite the lower height results. */
8552af58022SMatthew G. Knepley   for (h = minHeight; h <= maxHeight; h++) {
856636b9322SMatthew G. Knepley     PetscInt     hEff     = h - minHeight + htInc;
857636b9322SMatthew G. Knepley     PetscInt     hEffIn   = h - minHeight + htIncIn;
858636b9322SMatthew G. Knepley     PetscInt     hEffAux  = h - minHeight + htIncAux;
859a6e0b375SMatthew G. Knepley     PetscDS      dsEff    = ds;
860636b9322SMatthew G. Knepley     PetscDS      dsEffIn  = dsIn;
861636b9322SMatthew G. Knepley     PetscDS      dsEffAux = dsAux;
8628c6c5593SMatthew G. Knepley     PetscScalar *values;
863b7260050SToby Isaac     PetscBool   *fieldActive;
864b7260050SToby Isaac     PetscInt     maxDegree;
865e5e52638SMatthew G. Knepley     PetscInt     pStart, pEnd, p, lStart, spDim, totDim, numValues;
866c330f8ffSToby Isaac     IS           heightIS;
8678c6c5593SMatthew G. Knepley 
868636b9322SMatthew G. Knepley     if (h > minHeight) {
8699566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDualSpaceGetHeightSubspace(cellsp[f], hEff, &sp[f]));
870636b9322SMatthew G. Knepley     }
8719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSimplexOrBoxCells(plex, h, &pStart, &pEnd));
8729566063dSJacob Faibussowitsch     PetscCall(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, h, &lStart, NULL));
8739566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(depthLabel, depth - h, &heightIS));
874c330f8ffSToby Isaac     if (pEnd <= pStart) {
8759566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&heightIS));
876c330f8ffSToby Isaac       continue;
877c330f8ffSToby Isaac     }
87847923291SMatthew G. Knepley     /* Compute totDim, the number of dofs in the closure of a point at this height */
87947923291SMatthew G. Knepley     totDim = 0;
88047923291SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
8815fedec97SMatthew G. Knepley       PetscBool cohesive;
8825fedec97SMatthew G. Knepley 
883665f567fSMatthew G. Knepley       if (!sp[f]) continue;
8849566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
8859566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceGetDimension(sp[f], &spDim));
8869c3cf19fSMatthew G. Knepley       totDim += spDim;
8875fedec97SMatthew G. Knepley       if (isCohesive && !cohesive) totDim += spDim;
88847923291SMatthew G. Knepley     }
889636b9322SMatthew G. Knepley     p = lStart < 0 ? pStart : lStart;
8909566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(plex, section, localX, p, &numValues, NULL));
89163a3b9bcSJacob Faibussowitsch     PetscCheck(numValues == totDim, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The output section point (%" PetscInt_FMT ") closure size %" PetscInt_FMT " != dual space dimension %" PetscInt_FMT " at height %" PetscInt_FMT " in [%" PetscInt_FMT ", %" PetscInt_FMT "]", p, numValues, totDim, h, minHeight, maxHeight);
892c330f8ffSToby Isaac     if (!totDim) {
8939566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&heightIS));
894c330f8ffSToby Isaac       continue;
895c330f8ffSToby Isaac     }
8969566063dSJacob Faibussowitsch     if (htInc) PetscCall(PetscDSGetHeightSubspace(ds, hEff, &dsEff));
897636b9322SMatthew G. Knepley     /* Compute totDimIn, the number of dofs in the closure of a point at this height */
898636b9322SMatthew G. Knepley     if (localU) {
899636b9322SMatthew G. Knepley       PetscInt totDimIn, pIn, numValuesIn;
900636b9322SMatthew G. Knepley 
901636b9322SMatthew G. Knepley       totDimIn = 0;
902636b9322SMatthew G. Knepley       for (f = 0; f < NfIn; ++f) {
9035fedec97SMatthew G. Knepley         PetscBool cohesive;
9045fedec97SMatthew G. Knepley 
905636b9322SMatthew G. Knepley         if (!spIn[f]) continue;
9069566063dSJacob Faibussowitsch         PetscCall(PetscDSGetCohesive(dsIn, f, &cohesive));
9079566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetDimension(spIn[f], &spDim));
908636b9322SMatthew G. Knepley         totDimIn += spDim;
9098e6d238bSMatthew G. Knepley         if (isCohesiveIn && !cohesive) totDimIn += spDim;
910636b9322SMatthew G. Knepley       }
9119566063dSJacob Faibussowitsch       PetscCall(DMGetEnclosurePoint(dmIn, dm, encIn, lStart < 0 ? pStart : lStart, &pIn));
9129566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(plexIn, NULL, localU, pIn, &numValuesIn, NULL));
9138e6d238bSMatthew G. Knepley       // TODO We could check that pIn is a cohesive cell for this check
9148e6d238bSMatthew G. Knepley       PetscCheck(isCohesiveIn || (numValuesIn == totDimIn), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The input section point (%" PetscInt_FMT ") closure size %" PetscInt_FMT " != dual space dimension %" PetscInt_FMT " at height %" PetscInt_FMT, pIn, numValuesIn, totDimIn, htIncIn);
9159566063dSJacob Faibussowitsch       if (htIncIn) PetscCall(PetscDSGetHeightSubspace(dsIn, hEffIn, &dsEffIn));
916636b9322SMatthew G. Knepley     }
9179566063dSJacob Faibussowitsch     if (htIncAux) PetscCall(PetscDSGetHeightSubspace(dsAux, hEffAux, &dsEffAux));
91847923291SMatthew G. Knepley     /* Loop over points at this height */
9199566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numValues, MPIU_SCALAR, &values));
9209566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, NfTot, MPI_INT, &fieldActive));
921aa0eca99SMatthew G. Knepley     {
922aa0eca99SMatthew G. Knepley       const PetscInt *fields;
923aa0eca99SMatthew G. Knepley 
9249566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(fieldIS, &fields));
925ad540459SPierre Jolivet       for (f = 0; f < NfTot; ++f) fieldActive[f] = PETSC_FALSE;
926ad540459SPierre Jolivet       for (f = 0; f < Nf; ++f) fieldActive[fields[f]] = (funcs[f] && sp[f]) ? PETSC_TRUE : PETSC_FALSE;
9279566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(fieldIS, &fields));
928aa0eca99SMatthew G. Knepley     }
9298c6c5593SMatthew G. Knepley     if (label) {
9308c6c5593SMatthew G. Knepley       PetscInt i;
93147923291SMatthew G. Knepley 
93247923291SMatthew G. Knepley       for (i = 0; i < numIds; ++i) {
933c330f8ffSToby Isaac         IS              pointIS, isectIS;
93447923291SMatthew G. Knepley         const PetscInt *points;
9358c6c5593SMatthew G. Knepley         PetscInt        n;
936c330f8ffSToby Isaac         PetscFEGeom    *fegeom = NULL, *chunkgeom = NULL;
937c330f8ffSToby Isaac         PetscQuadrature quad = NULL;
93847923291SMatthew G. Knepley 
9399566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumIS(label, ids[i], &pointIS));
94047923291SMatthew G. Knepley         if (!pointIS) continue; /* No points with that id on this process */
9419566063dSJacob Faibussowitsch         PetscCall(ISIntersect(pointIS, heightIS, &isectIS));
9429566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&pointIS));
943c330f8ffSToby Isaac         if (!isectIS) continue;
9449566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(isectIS, &n));
9459566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(isectIS, &points));
9469566063dSJacob Faibussowitsch         PetscCall(DMFieldGetDegree(coordField, isectIS, NULL, &maxDegree));
94748a46eb9SPierre Jolivet         if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, isectIS, &quad));
948c330f8ffSToby Isaac         if (!quad) {
949c330f8ffSToby Isaac           if (!h && allPoints) {
950c330f8ffSToby Isaac             quad      = allPoints;
951c330f8ffSToby Isaac             allPoints = NULL;
952c330f8ffSToby Isaac           } else {
9539566063dSJacob Faibussowitsch             PetscCall(PetscDualSpaceGetAllPointsUnion(Nf, sp, isCohesive ? dim - htInc - 1 : dim - htInc, funcs, &quad));
954c330f8ffSToby Isaac           }
955c330f8ffSToby Isaac         }
95679f2dbaeSMatthew G. Knepley         PetscBool computeFaceGeom = htInc && h == minHeight ? PETSC_TRUE : PETSC_FALSE;
95779f2dbaeSMatthew G. Knepley 
95879f2dbaeSMatthew G. Knepley         if (n) {
95979f2dbaeSMatthew G. Knepley           PetscInt depth, dep;
96079f2dbaeSMatthew G. Knepley 
96179f2dbaeSMatthew G. Knepley           PetscCall(DMPlexGetDepth(dm, &depth));
96279f2dbaeSMatthew G. Knepley           PetscCall(DMPlexGetPointDepth(dm, points[0], &dep));
96379f2dbaeSMatthew G. Knepley           if (dep < depth && h == minHeight) computeFaceGeom = PETSC_TRUE;
96479f2dbaeSMatthew G. Knepley         }
96579f2dbaeSMatthew G. Knepley         PetscCall(DMFieldCreateFEGeom(coordField, isectIS, quad, computeFaceGeom, &fegeom));
96647923291SMatthew G. Knepley         for (p = 0; p < n; ++p) {
96747923291SMatthew G. Knepley           const PetscInt point = points[p];
96847923291SMatthew G. Knepley 
9699566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(values, numValues));
9709566063dSJacob Faibussowitsch           PetscCall(PetscFEGeomGetChunk(fegeom, p, p + 1, &chunkgeom));
9719566063dSJacob Faibussowitsch           PetscCall(DMPlexSetActivePoint(dm, point));
972d0609cedSBarry Smith           PetscCall(DMProjectPoint_Private(dm, dsEff, plexIn, encIn, dsEffIn, plexAux, encAux, dsEffAux, chunkgeom, htInc, time, localU, localA, hasFE, hasFV, isFE, sp, point, T, TAux, type, funcs, ctxs, fieldActive, values));
9739566063dSJacob Faibussowitsch           if (transform) PetscCall(DMPlexBasisTransformPoint_Internal(plex, tdm, tv, point, fieldActive, PETSC_FALSE, values));
9749566063dSJacob Faibussowitsch           PetscCall(DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, point, Ncc, comps, label, ids[i], values, mode));
97547923291SMatthew G. Knepley         }
9769566063dSJacob Faibussowitsch         PetscCall(PetscFEGeomRestoreChunk(fegeom, p, p + 1, &chunkgeom));
9779566063dSJacob Faibussowitsch         PetscCall(PetscFEGeomDestroy(&fegeom));
9789566063dSJacob Faibussowitsch         PetscCall(PetscQuadratureDestroy(&quad));
9799566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(isectIS, &points));
9809566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&isectIS));
98147923291SMatthew G. Knepley       }
9828c6c5593SMatthew G. Knepley     } else {
983c330f8ffSToby Isaac       PetscFEGeom    *fegeom = NULL, *chunkgeom = NULL;
984c330f8ffSToby Isaac       PetscQuadrature quad = NULL;
985c330f8ffSToby Isaac       IS              pointIS;
986c330f8ffSToby Isaac 
9879566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pointIS));
9889566063dSJacob Faibussowitsch       PetscCall(DMFieldGetDegree(coordField, pointIS, NULL, &maxDegree));
98948a46eb9SPierre Jolivet       if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, pointIS, &quad));
990c330f8ffSToby Isaac       if (!quad) {
991c330f8ffSToby Isaac         if (!h && allPoints) {
992c330f8ffSToby Isaac           quad      = allPoints;
993c330f8ffSToby Isaac           allPoints = NULL;
994c330f8ffSToby Isaac         } else {
9959566063dSJacob Faibussowitsch           PetscCall(PetscDualSpaceGetAllPointsUnion(Nf, sp, dim - htInc, funcs, &quad));
996c330f8ffSToby Isaac         }
997c330f8ffSToby Isaac       }
9989566063dSJacob Faibussowitsch       PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, (htInc && h == minHeight) ? PETSC_TRUE : PETSC_FALSE, &fegeom));
9998c6c5593SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
10009566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(values, numValues));
10019566063dSJacob Faibussowitsch         PetscCall(PetscFEGeomGetChunk(fegeom, p - pStart, p - pStart + 1, &chunkgeom));
10029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetActivePoint(dm, p));
1003d0609cedSBarry Smith         PetscCall(DMProjectPoint_Private(dm, dsEff, plexIn, encIn, dsEffIn, plexAux, encAux, dsEffAux, chunkgeom, htInc, time, localU, localA, hasFE, hasFV, isFE, sp, p, T, TAux, type, funcs, ctxs, fieldActive, values));
10049566063dSJacob Faibussowitsch         if (transform) PetscCall(DMPlexBasisTransformPoint_Internal(plex, tdm, tv, p, fieldActive, PETSC_FALSE, values));
10059566063dSJacob Faibussowitsch         PetscCall(DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, p, Ncc, comps, NULL, -1, values, mode));
10068c6c5593SMatthew G. Knepley       }
10079566063dSJacob Faibussowitsch       PetscCall(PetscFEGeomRestoreChunk(fegeom, p - pStart, pStart - p + 1, &chunkgeom));
10089566063dSJacob Faibussowitsch       PetscCall(PetscFEGeomDestroy(&fegeom));
10099566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureDestroy(&quad));
10109566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
10118c6c5593SMatthew G. Knepley     }
10129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&heightIS));
10139566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values));
10149566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive));
101547923291SMatthew G. Knepley   }
10168c6c5593SMatthew G. Knepley   /* Cleanup */
1017ece3a9fcSMatthew G. Knepley   if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) {
10189566063dSJacob Faibussowitsch     for (f = 0; f < NfIn; ++f) PetscCall(PetscTabulationDestroy(&T[f]));
10199566063dSJacob Faibussowitsch     for (f = 0; f < NfAux; ++f) PetscCall(PetscTabulationDestroy(&TAux[f]));
10209566063dSJacob Faibussowitsch     PetscCall(PetscFree2(T, TAux));
10210c898c18SMatthew G. Knepley   }
10229566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&allPoints));
10239566063dSJacob Faibussowitsch   PetscCall(PetscFree3(isFE, sp, spIn));
10249566063dSJacob Faibussowitsch   if (maxHeight > 0) PetscCall(PetscFree2(cellsp, cellspIn));
10259566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
10269566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plexIn));
10279566063dSJacob Faibussowitsch   if (dmAux) PetscCall(DMDestroy(&plexAux));
10283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102947923291SMatthew G. Knepley }
10308c6c5593SMatthew G. Knepley 
1031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLocal_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
1032d71ae5a4SJacob Faibussowitsch {
10338c6c5593SMatthew G. Knepley   PetscFunctionBegin;
10349566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, NULL, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL, (void (**)(void))funcs, ctxs, mode, localX));
10353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10368c6c5593SMatthew G. Knepley }
10378c6c5593SMatthew G. Knepley 
1038d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
1039d71ae5a4SJacob Faibussowitsch {
10408c6c5593SMatthew G. Knepley   PetscFunctionBegin;
10419566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, NULL, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL, (void (**)(void))funcs, ctxs, mode, localX));
10423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104347923291SMatthew G. Knepley }
104447923291SMatthew G. Knepley 
1045d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFieldLocal_Plex(DM dm, PetscReal time, Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX)
1046d71ae5a4SJacob Faibussowitsch {
104747923291SMatthew G. Knepley   PetscFunctionBegin;
10489566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, localU, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL_FIELD, (void (**)(void))funcs, NULL, mode, localX));
10493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105047923291SMatthew G. Knepley }
105147923291SMatthew G. Knepley 
1052d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFieldLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX)
1053d71ae5a4SJacob Faibussowitsch {
10548c6c5593SMatthew G. Knepley   PetscFunctionBegin;
10559566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_FIELD, (void (**)(void))funcs, NULL, mode, localX));
10563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105747923291SMatthew G. Knepley }
1058ece3a9fcSMatthew G. Knepley 
1059d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectBdFieldLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX)
1060d71ae5a4SJacob Faibussowitsch {
1061ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
10629566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_BD_FIELD, (void (**)(void))funcs, NULL, mode, localX));
10633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1064ece3a9fcSMatthew G. Knepley }
1065