xref: /petsc/src/dm/impls/plex/plexproject.c (revision a1cb98fac0cdf0eb4d3e8a0c8b58f3fe8f800bc6)
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 
81b32699bSMatthew G. Knepley   Not collective
91b32699bSMatthew G. Knepley 
104165533cSJose E. Roman   Input Parameter:
11*a1cb98faSBarry 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 
18*a1cb98faSBarry Smith .seealso: [](chapter_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;
241b32699bSMatthew G. Knepley   PetscFunctionReturn(0);
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 
301b32699bSMatthew G. Knepley   Not collective
311b32699bSMatthew G. Knepley 
324165533cSJose E. Roman   Input Parameters:
33*a1cb98faSBarry 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 
38*a1cb98faSBarry Smith .seealso: [](chapter_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;
441b32699bSMatthew G. Knepley   PetscFunctionReturn(0);
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:
51*a1cb98faSBarry Smith + dm     - The output `DM`
52*a1cb98faSBarry Smith . ds     - The output `DS`
53*a1cb98faSBarry Smith . dmIn   - The input `DM`
54*a1cb98faSBarry 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
59*a1cb98faSBarry 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 
68*a1cb98faSBarry Smith .seealso:[](chapter_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   }
1498c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
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 
178*a1cb98faSBarry Smith   Note:
179*a1cb98faSBarry Smith   Not supported for FV
180*a1cb98faSBarry 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;
191ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nc;
1924bee2e38SMatthew G. Knepley   PetscFEGeom        fegeom;
1934bee2e38SMatthew G. Knepley   const PetscInt     dE = cgeom->dimEmbed;
194ef0bb6c7SMatthew G. Knepley   PetscInt           numConstants, Nf, NfIn, NfAux = 0, f, spDim, d, v, inp, tp = 0;
1955fedec97SMatthew G. Knepley   PetscBool          isAffine, isCohesive, transform;
1968c6c5593SMatthew G. Knepley 
1978c6c5593SMatthew G. Knepley   PetscFunctionBeginHot;
1989566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
1999566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
2009566063dSJacob Faibussowitsch   PetscCall(PetscDSIsCohesive(ds, &isCohesive));
2019566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(dsIn, &NfIn));
2029566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponentOffsets(dsIn, &uOff));
2039566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponentDerivativeOffsets(dsIn, &uOff_x));
2049566063dSJacob Faibussowitsch   PetscCall(PetscDSGetEvaluationArrays(dsIn, &u, &bc /*&u_t*/, &u_x));
2059566063dSJacob Faibussowitsch   PetscCall(PetscDSGetWorkspace(dsIn, &x, NULL, NULL, NULL, NULL));
2069566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(dsIn, &numConstants, &constants));
2079566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dmIn, &transform));
2089566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmIn, &section));
2099566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosurePoint(dmIn, dm, encIn, p, &inp));
2109566063dSJacob Faibussowitsch   PetscCall(DMPlexVecGetClosure(dmIn, section, localU, inp, NULL, &coefficients));
2118c6c5593SMatthew G. Knepley   if (dmAux) {
21244171101SMatthew G. Knepley     PetscInt subp;
2131ba34526SMatthew G. Knepley 
2149566063dSJacob Faibussowitsch     PetscCall(DMGetEnclosurePoint(dmAux, dm, encAux, p, &subp));
2159566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(dsAux, &NfAux));
2169566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dmAux, &sectionAux));
2179566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff));
2189566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x));
2199566063dSJacob Faibussowitsch     PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL /*&a_t*/, &a_x));
2209566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmAux, sectionAux, localA, subp, NULL, &coefficientsAux));
2218c6c5593SMatthew G. Knepley   }
2228c6c5593SMatthew G. Knepley   /* Get values for closure */
2234bee2e38SMatthew G. Knepley   isAffine        = cgeom->isAffine;
22427f02ce8SMatthew G. Knepley   fegeom.dim      = cgeom->dim;
22527f02ce8SMatthew G. Knepley   fegeom.dimEmbed = cgeom->dimEmbed;
2264bee2e38SMatthew G. Knepley   if (isAffine) {
2274bee2e38SMatthew G. Knepley     fegeom.v    = x;
2284bee2e38SMatthew G. Knepley     fegeom.xi   = cgeom->xi;
2294bee2e38SMatthew G. Knepley     fegeom.J    = cgeom->J;
2304bee2e38SMatthew G. Knepley     fegeom.invJ = cgeom->invJ;
2314bee2e38SMatthew G. Knepley     fegeom.detJ = cgeom->detJ;
2324bee2e38SMatthew G. Knepley   }
2338c6c5593SMatthew G. Knepley   for (f = 0, v = 0; f < Nf; ++f) {
234c330f8ffSToby Isaac     PetscQuadrature  allPoints;
235c330f8ffSToby Isaac     PetscInt         q, dim, numPoints;
236c330f8ffSToby Isaac     const PetscReal *points;
237c330f8ffSToby Isaac     PetscScalar     *pointEval;
2385fedec97SMatthew G. Knepley     PetscBool        cohesive;
239c330f8ffSToby Isaac     DM               dm;
240c330f8ffSToby Isaac 
2418c6c5593SMatthew G. Knepley     if (!sp[f]) continue;
2429566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
2439566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDimension(sp[f], &spDim));
244c330f8ffSToby Isaac     if (!funcs[f]) {
245be1504a2SMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = 0.;
2465fedec97SMatthew G. Knepley       if (isCohesive && !cohesive) {
24727f02ce8SMatthew G. Knepley         for (d = 0; d < spDim; d++, v++) values[v] = 0.;
24827f02ce8SMatthew G. Knepley       }
249c330f8ffSToby Isaac       continue;
250c330f8ffSToby Isaac     }
2519566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDM(sp[f], &dm));
2529566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL));
2539566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(allPoints, &dim, NULL, &numPoints, &points, NULL));
2549566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
2550c898c18SMatthew G. Knepley     for (q = 0; q < numPoints; ++q, ++tp) {
256c330f8ffSToby Isaac       if (isAffine) {
257ef0bb6c7SMatthew G. Knepley         CoordinatesRefToReal(dE, cgeom->dim, fegeom.xi, cgeom->v, fegeom.J, &points[q * dim], x);
2581c531cf8SMatthew G. Knepley       } else {
2594bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[tp * dE];
2604bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[tp * dE * dE];
2614bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[tp * dE * dE];
2624bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[tp];
2638c6c5593SMatthew G. Knepley       }
2649566063dSJacob Faibussowitsch       PetscCall(PetscFEEvaluateFieldJets_Internal(dsIn, NfIn, 0, tp, T, &fegeom, coefficients, coefficients_t, u, u_x, u_t));
2659566063dSJacob Faibussowitsch       if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, tp, TAux, &fegeom, coefficientsAux, coefficientsAux_t, a, a_x, a_t));
2669566063dSJacob Faibussowitsch       if (transform) PetscCall(DMPlexBasisTransformApplyReal_Internal(dmIn, fegeom.v, PETSC_TRUE, dE, fegeom.v, fegeom.v, dm->transformCtx));
267a6e0b375SMatthew 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]);
2681c531cf8SMatthew G. Knepley     }
2699566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v]));
2709566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
271c330f8ffSToby Isaac     v += spDim;
27227f02ce8SMatthew G. Knepley     /* TODO: For now, set both sides equal, but this should use info from other support cell */
2735fedec97SMatthew G. Knepley     if (isCohesive && !cohesive) {
27427f02ce8SMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = values[v - spDim];
27527f02ce8SMatthew G. Knepley     }
2768c6c5593SMatthew G. Knepley   }
2779566063dSJacob Faibussowitsch   PetscCall(DMPlexVecRestoreClosure(dmIn, section, localU, inp, NULL, &coefficients));
2789566063dSJacob Faibussowitsch   if (dmAux) PetscCall(DMPlexVecRestoreClosure(dmAux, sectionAux, localA, p, NULL, &coefficientsAux));
2798c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
2808c6c5593SMatthew G. Knepley }
2818c6c5593SMatthew G. Knepley 
282d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectPoint_BdField_Private(DM dm, PetscDS ds, DM dmIn, 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[])
283d71ae5a4SJacob Faibussowitsch {
284b18799e0SMatthew G. Knepley   PetscSection       section, sectionAux = NULL;
2854bee2e38SMatthew G. Knepley   PetscScalar       *u, *u_t = NULL, *u_x, *a = NULL, *a_t = NULL, *a_x = NULL, *bc;
286b18799e0SMatthew G. Knepley   PetscScalar       *coefficients = NULL, *coefficientsAux = NULL;
287b18799e0SMatthew G. Knepley   PetscScalar       *coefficients_t = NULL, *coefficientsAux_t = NULL;
288b18799e0SMatthew G. Knepley   const PetscScalar *constants;
289b18799e0SMatthew G. Knepley   PetscReal         *x;
290ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nc;
2919f209ee4SMatthew G. Knepley   PetscFEGeom        fegeom, cgeom;
2924bee2e38SMatthew G. Knepley   const PetscInt     dE = fgeom->dimEmbed;
293ef0bb6c7SMatthew G. Knepley   PetscInt           numConstants, Nf, NfAux = 0, f, spDim, d, v, tp = 0;
294b18799e0SMatthew G. Knepley   PetscBool          isAffine;
295b18799e0SMatthew G. Knepley 
296b18799e0SMatthew G. Knepley   PetscFunctionBeginHot;
29708401ef6SPierre Jolivet   PetscCheck(dm == dmIn, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not yet upgraded to use different input DM");
2989566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
2999566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
3009566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponentOffsets(ds, &uOff));
3019566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x));
3029566063dSJacob Faibussowitsch   PetscCall(PetscDSGetEvaluationArrays(ds, &u, &bc /*&u_t*/, &u_x));
3039566063dSJacob Faibussowitsch   PetscCall(PetscDSGetWorkspace(ds, &x, NULL, NULL, NULL, NULL));
3049566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(ds, &numConstants, &constants));
3059566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
3069566063dSJacob Faibussowitsch   PetscCall(DMPlexVecGetClosure(dmIn, section, localU, p, NULL, &coefficients));
307b18799e0SMatthew G. Knepley   if (dmAux) {
308a6e0b375SMatthew G. Knepley     PetscInt subp;
309b18799e0SMatthew G. Knepley 
3109566063dSJacob Faibussowitsch     PetscCall(DMGetEnclosurePoint(dmAux, dm, encAux, p, &subp));
3119566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(dsAux, &NfAux));
3129566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dmAux, &sectionAux));
3139566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff));
3149566063dSJacob Faibussowitsch     PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x));
3159566063dSJacob Faibussowitsch     PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL /*&a_t*/, &a_x));
3169566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmAux, sectionAux, localA, subp, NULL, &coefficientsAux));
317b18799e0SMatthew G. Knepley   }
318b18799e0SMatthew G. Knepley   /* Get values for closure */
3194bee2e38SMatthew G. Knepley   isAffine       = fgeom->isAffine;
320ea78f98cSLisandro Dalcin   fegeom.n       = NULL;
321ea78f98cSLisandro Dalcin   fegeom.J       = NULL;
322ea78f98cSLisandro Dalcin   fegeom.v       = NULL;
323ea78f98cSLisandro Dalcin   fegeom.xi      = NULL;
324a6e0b375SMatthew G. Knepley   cgeom.dim      = fgeom->dim;
325a6e0b375SMatthew G. Knepley   cgeom.dimEmbed = fgeom->dimEmbed;
3264bee2e38SMatthew G. Knepley   if (isAffine) {
3274bee2e38SMatthew G. Knepley     fegeom.v    = x;
3284bee2e38SMatthew G. Knepley     fegeom.xi   = fgeom->xi;
3294bee2e38SMatthew G. Knepley     fegeom.J    = fgeom->J;
3304bee2e38SMatthew G. Knepley     fegeom.invJ = fgeom->invJ;
3314bee2e38SMatthew G. Knepley     fegeom.detJ = fgeom->detJ;
3324bee2e38SMatthew G. Knepley     fegeom.n    = fgeom->n;
3339f209ee4SMatthew G. Knepley 
3349f209ee4SMatthew G. Knepley     cgeom.J    = fgeom->suppJ[0];
3359f209ee4SMatthew G. Knepley     cgeom.invJ = fgeom->suppInvJ[0];
3369f209ee4SMatthew G. Knepley     cgeom.detJ = fgeom->suppDetJ[0];
3374bee2e38SMatthew G. Knepley   }
338b18799e0SMatthew G. Knepley   for (f = 0, v = 0; f < Nf; ++f) {
339b18799e0SMatthew G. Knepley     PetscQuadrature  allPoints;
340b18799e0SMatthew G. Knepley     PetscInt         q, dim, numPoints;
341b18799e0SMatthew G. Knepley     const PetscReal *points;
342b18799e0SMatthew G. Knepley     PetscScalar     *pointEval;
343b18799e0SMatthew G. Knepley     DM               dm;
344b18799e0SMatthew G. Knepley 
345b18799e0SMatthew G. Knepley     if (!sp[f]) continue;
3469566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDimension(sp[f], &spDim));
347b18799e0SMatthew G. Knepley     if (!funcs[f]) {
348b18799e0SMatthew G. Knepley       for (d = 0; d < spDim; d++, v++) values[v] = 0.;
349b18799e0SMatthew G. Knepley       continue;
350b18799e0SMatthew G. Knepley     }
3519566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetDM(sp[f], &dm));
3529566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL));
3539566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(allPoints, &dim, NULL, &numPoints, &points, NULL));
3549566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
355b18799e0SMatthew G. Knepley     for (q = 0; q < numPoints; ++q, ++tp) {
356b18799e0SMatthew G. Knepley       if (isAffine) {
357ef0bb6c7SMatthew G. Knepley         CoordinatesRefToReal(dE, fgeom->dim, fegeom.xi, fgeom->v, fegeom.J, &points[q * dim], x);
358b18799e0SMatthew G. Knepley       } else {
3593fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[tp * dE];
3609f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[tp * dE * dE];
3619f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[tp * dE * dE];
3624bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[tp];
3634bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[tp * dE];
3649f209ee4SMatthew G. Knepley 
3659f209ee4SMatthew G. Knepley         cgeom.J    = &fgeom->suppJ[0][tp * dE * dE];
3669f209ee4SMatthew G. Knepley         cgeom.invJ = &fgeom->suppInvJ[0][tp * dE * dE];
3679f209ee4SMatthew G. Knepley         cgeom.detJ = &fgeom->suppDetJ[0][tp];
368b18799e0SMatthew G. Knepley       }
369a6e0b375SMatthew 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 */
3709566063dSJacob Faibussowitsch       PetscCall(PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, tp, T, &cgeom, coefficients, coefficients_t, u, u_x, u_t));
3719566063dSJacob Faibussowitsch       if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, tp, TAux, &cgeom, coefficientsAux, coefficientsAux_t, a, a_x, a_t));
3724bee2e38SMatthew G. Knepley       (*funcs[f])(dE, Nf, 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]);
373b18799e0SMatthew G. Knepley     }
3749566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v]));
3759566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints * Nc[f], MPIU_SCALAR, &pointEval));
376b18799e0SMatthew G. Knepley     v += spDim;
377b18799e0SMatthew G. Knepley   }
3789566063dSJacob Faibussowitsch   PetscCall(DMPlexVecRestoreClosure(dmIn, section, localU, p, NULL, &coefficients));
3799566063dSJacob Faibussowitsch   if (dmAux) PetscCall(DMPlexVecRestoreClosure(dmAux, sectionAux, localA, p, NULL, &coefficientsAux));
380b18799e0SMatthew G. Knepley   PetscFunctionReturn(0);
381b18799e0SMatthew G. Knepley }
382b18799e0SMatthew G. Knepley 
383d71ae5a4SJacob 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[])
384d71ae5a4SJacob Faibussowitsch {
3858c6c5593SMatthew G. Knepley   PetscFVCellGeom fvgeom;
3868c6c5593SMatthew G. Knepley   PetscInt        dim, dimEmbed;
3878c6c5593SMatthew G. Knepley 
3888c6c5593SMatthew G. Knepley   PetscFunctionBeginHot;
3899566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
3909566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
3919566063dSJacob Faibussowitsch   if (hasFV) PetscCall(DMPlexComputeCellGeometryFVM(dm, p, &fvgeom.volume, fvgeom.centroid, NULL));
3928c6c5593SMatthew G. Knepley   switch (type) {
3938c6c5593SMatthew G. Knepley   case DM_BC_ESSENTIAL:
394d71ae5a4SJacob Faibussowitsch   case DM_BC_NATURAL:
395d71ae5a4SJacob 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));
396d71ae5a4SJacob Faibussowitsch     break;
3978c6c5593SMatthew G. Knepley   case DM_BC_ESSENTIAL_FIELD:
3988c6c5593SMatthew G. Knepley   case DM_BC_NATURAL_FIELD:
3999371c9d4SSatish 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));
400d0609cedSBarry Smith     break;
401b18799e0SMatthew G. Knepley   case DM_BC_ESSENTIAL_BD_FIELD:
4029371c9d4SSatish Balay     PetscCall(DMProjectPoint_BdField_Private(dm, ds, dmIn, 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));
403d0609cedSBarry Smith     break;
404d71ae5a4SJacob Faibussowitsch   default:
405d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown boundary condition type: %d", (int)type);
4068c6c5593SMatthew G. Knepley   }
4078c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
4088c6c5593SMatthew G. Knepley }
4098c6c5593SMatthew G. Knepley 
410d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceGetAllPointsUnion(PetscInt Nf, PetscDualSpace *sp, PetscInt dim, void (**funcs)(void), PetscQuadrature *allPoints)
411d71ae5a4SJacob Faibussowitsch {
412df5c1128SToby Isaac   PetscReal *points;
413df5c1128SToby Isaac   PetscInt   f, numPoints;
414df5c1128SToby Isaac 
415df5c1128SToby Isaac   PetscFunctionBegin;
41619552267SMatthew G. Knepley   if (!dim) {
41719552267SMatthew G. Knepley     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allPoints));
41819552267SMatthew G. Knepley     PetscFunctionReturn(0);
41919552267SMatthew G. Knepley   }
420df5c1128SToby Isaac   numPoints = 0;
421df5c1128SToby Isaac   for (f = 0; f < Nf; ++f) {
422df5c1128SToby Isaac     if (funcs[f]) {
423df5c1128SToby Isaac       PetscQuadrature fAllPoints;
424df5c1128SToby Isaac       PetscInt        fNumPoints;
425df5c1128SToby Isaac 
4269566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceGetAllData(sp[f], &fAllPoints, NULL));
4279566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureGetData(fAllPoints, NULL, NULL, &fNumPoints, NULL, NULL));
428df5c1128SToby Isaac       numPoints += fNumPoints;
429df5c1128SToby Isaac     }
430df5c1128SToby Isaac   }
4319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dim * numPoints, &points));
432df5c1128SToby Isaac   numPoints = 0;
433df5c1128SToby Isaac   for (f = 0; f < Nf; ++f) {
434df5c1128SToby Isaac     if (funcs[f]) {
435df5c1128SToby Isaac       PetscQuadrature  fAllPoints;
43654ee0cceSMatthew G. Knepley       PetscInt         qdim, fNumPoints, q;
437df5c1128SToby Isaac       const PetscReal *fPoints;
438df5c1128SToby Isaac 
4399566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceGetAllData(sp[f], &fAllPoints, NULL));
4409566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureGetData(fAllPoints, &qdim, NULL, &fNumPoints, &fPoints, NULL));
44163a3b9bcSJacob 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);
442df5c1128SToby Isaac       for (q = 0; q < fNumPoints * dim; ++q) points[numPoints * dim + q] = fPoints[q];
443df5c1128SToby Isaac       numPoints += fNumPoints;
444df5c1128SToby Isaac     }
445df5c1128SToby Isaac   }
4469566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allPoints));
4479566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureSetData(*allPoints, dim, 0, numPoints, points, NULL));
448df5c1128SToby Isaac   PetscFunctionReturn(0);
449df5c1128SToby Isaac }
450df5c1128SToby Isaac 
4515f15299fSJeremy L Thompson /*@C
4525f15299fSJeremy L Thompson   DMGetFirstLabeledPoint - Find first labeled point p_o in odm such that the corresponding point p in dm has the specified height. Return p and the corresponding ds.
4535f15299fSJeremy L Thompson 
4545f15299fSJeremy L Thompson   Input Parameters:
455*a1cb98faSBarry Smith   dm - the `DM`
456*a1cb98faSBarry Smith   odm - the enclosing `DM`
457*a1cb98faSBarry Smith   label - label for `DM` domain, or NULL for whole domain
4585f15299fSJeremy L Thompson   numIds - the number of ids
4595f15299fSJeremy L Thompson   ids - An array of the label ids in sequence for the domain
460*a1cb98faSBarry Smith   height - Height of target cells in `DMPLEX` topology
4615f15299fSJeremy L Thompson 
4625f15299fSJeremy L Thompson   Output Parameters:
4635f15299fSJeremy L Thompson   point - the first labeled point
4645f15299fSJeremy L Thompson   ds - the ds corresponding to the first labeled point
4655f15299fSJeremy L Thompson 
4665f15299fSJeremy L Thompson   Level: developer
467*a1cb98faSBarry Smith 
468*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetActivePoint()`, `DMLabel`, `PetscDS`
469817da375SSatish Balay @*/
470d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFirstLabeledPoint(DM dm, DM odm, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt height, PetscInt *point, PetscDS *ds)
471d71ae5a4SJacob Faibussowitsch {
472a6e0b375SMatthew G. Knepley   DM              plex;
473a6e0b375SMatthew G. Knepley   DMEnclosureType enc;
474e9f0ba4eSJed Brown   PetscInt        ls = -1;
475e5e52638SMatthew G. Knepley 
476e5e52638SMatthew G. Knepley   PetscFunctionBegin;
4775f15299fSJeremy L Thompson   if (point) *point = -1;
478e5e52638SMatthew G. Knepley   if (!label) PetscFunctionReturn(0);
4799566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosureRelation(dm, odm, &enc));
4809566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
481e9f0ba4eSJed Brown   for (PetscInt i = 0; i < numIds; ++i) {
482e9f0ba4eSJed Brown     IS       labelIS;
483e9f0ba4eSJed Brown     PetscInt num_points, pStart, pEnd;
4849566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, ids[i], &labelIS));
485e9f0ba4eSJed Brown     if (!labelIS) continue; /* No points with that id on this process */
4869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(plex, height, &pStart, &pEnd));
4879566063dSJacob Faibussowitsch     PetscCall(ISGetSize(labelIS, &num_points));
488e9f0ba4eSJed Brown     if (num_points) {
489e5e52638SMatthew G. Knepley       const PetscInt *points;
4909566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(labelIS, &points));
491e9f0ba4eSJed Brown       for (PetscInt i = 0; i < num_points; i++) {
492e9f0ba4eSJed Brown         PetscInt point;
4939566063dSJacob Faibussowitsch         PetscCall(DMGetEnclosurePoint(dm, odm, enc, points[i], &point));
494e9f0ba4eSJed Brown         if (pStart <= point && point < pEnd) {
495a6e0b375SMatthew G. Knepley           ls = point;
4969566063dSJacob Faibussowitsch           if (ds) PetscCall(DMGetCellDS(dm, ls, ds));
497e5e52638SMatthew G. Knepley         }
498e9f0ba4eSJed Brown       }
4999566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(labelIS, &points));
500e9f0ba4eSJed Brown     }
5019566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&labelIS));
502e5e52638SMatthew G. Knepley     if (ls >= 0) break;
503e5e52638SMatthew G. Knepley   }
5045f15299fSJeremy L Thompson   if (point) *point = ls;
5059566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
506e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
507e5e52638SMatthew G. Knepley }
508e5e52638SMatthew G. Knepley 
5090de51b56SMatthew G. Knepley /*
5100de51b56SMatthew G. Knepley   This function iterates over a manifold, and interpolates the input function/field using the basis provided by the DS in our DM
5110de51b56SMatthew G. Knepley 
5120de51b56SMatthew G. Knepley   There are several different scenarios:
5130de51b56SMatthew G. Knepley 
5140de51b56SMatthew G. Knepley   1) Volumetric mesh with volumetric auxiliary data
5150de51b56SMatthew G. Knepley 
5160de51b56SMatthew G. Knepley      Here minHeight=0 since we loop over cells.
5170de51b56SMatthew G. Knepley 
5180de51b56SMatthew G. Knepley   2) Boundary mesh with boundary auxiliary data
5190de51b56SMatthew G. Knepley 
5200de51b56SMatthew 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.
5210de51b56SMatthew G. Knepley 
5220de51b56SMatthew G. Knepley   3) Volumetric mesh with boundary auxiliary data
5230de51b56SMatthew G. Knepley 
5240de51b56SMatthew 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.
5250de51b56SMatthew G. Knepley 
526636b9322SMatthew G. Knepley   4) Volumetric input mesh with boundary output mesh
527636b9322SMatthew G. Knepley 
528636b9322SMatthew G. Knepley      Here we must get a subspace for the input DS
529636b9322SMatthew G. Knepley 
5300de51b56SMatthew G. Knepley   The maxHeight is used to support enforcement of constraints in DMForest.
5310de51b56SMatthew G. Knepley 
5320de51b56SMatthew G. Knepley   If localU is given and not equal to localX, we call DMPlexInsertBoundaryValues() to complete it.
5330de51b56SMatthew G. Knepley 
5340de51b56SMatthew 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.
5350de51b56SMatthew 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
5365f790a90SMatthew 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
5370de51b56SMatthew G. Knepley       dual spaces for the boundary from our input spaces.
5380de51b56SMatthew G. Knepley     - After extracting all quadrature points, we tabulate the input fields and auxiliary fields on them.
5390de51b56SMatthew G. Knepley 
5400de51b56SMatthew G. Knepley   We check that the #dof(closure(p)) == #dual basis functionals(p) for a representative p in the iteration
5410de51b56SMatthew G. Knepley 
5420de51b56SMatthew 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.
5430de51b56SMatthew G. Knepley */
544d71ae5a4SJacob 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)
545d71ae5a4SJacob Faibussowitsch {
546a6e0b375SMatthew G. Knepley   DM               plex, dmIn, plexIn, dmAux = NULL, plexAux = NULL, tdm;
547a6e0b375SMatthew G. Knepley   DMEnclosureType  encIn, encAux;
548a6e0b375SMatthew G. Knepley   PetscDS          ds = NULL, dsIn = NULL, dsAux = NULL;
549ca3d3a14SMatthew G. Knepley   Vec              localA = NULL, tv;
550aa0eca99SMatthew G. Knepley   IS               fieldIS;
55147923291SMatthew G. Knepley   PetscSection     section;
552636b9322SMatthew G. Knepley   PetscDualSpace  *sp, *cellsp, *spIn, *cellspIn;
553ef0bb6c7SMatthew G. Knepley   PetscTabulation *T = NULL, *TAux = NULL;
5548c6c5593SMatthew G. Knepley   PetscInt        *Nc;
555636b9322SMatthew G. Knepley   PetscInt         dim, dimEmbed, depth, htInc = 0, htIncIn = 0, htIncAux = 0, minHeight, maxHeight, h, regionNum, Nf, NfIn, NfAux = 0, NfTot, f;
5565fedec97SMatthew G. Knepley   PetscBool       *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE, isCohesive = PETSC_FALSE, transform;
557c330f8ffSToby Isaac   DMField          coordField;
558c330f8ffSToby Isaac   DMLabel          depthLabel;
559c330f8ffSToby Isaac   PetscQuadrature  allPoints = NULL;
56047923291SMatthew G. Knepley 
56147923291SMatthew G. Knepley   PetscFunctionBegin;
5629566063dSJacob Faibussowitsch   if (localU) PetscCall(VecGetDM(localU, &dmIn));
563ad540459SPierre Jolivet   else dmIn = dm;
5649566063dSJacob Faibussowitsch   PetscCall(DMGetAuxiliaryVec(dm, label, numIds ? ids[0] : 0, 0, &localA));
5659371c9d4SSatish Balay   if (localA) PetscCall(VecGetDM(localA, &dmAux));
566ad540459SPierre Jolivet   else dmAux = NULL;
5679566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
5689566063dSJacob Faibussowitsch   PetscCall(DMConvert(dmIn, DMPLEX, &plexIn));
5699566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosureRelation(dmIn, dm, &encIn));
5709566063dSJacob Faibussowitsch   PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
5719566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(plex, &minHeight));
5739566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
5749566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
5759566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dm, &transform));
5760de51b56SMatthew G. Knepley   /* Auxiliary information can only be used with interpolation of field functions */
577a6e0b375SMatthew G. Knepley   if (dmAux) {
5789566063dSJacob Faibussowitsch     PetscCall(DMConvert(dmAux, DMPLEX, &plexAux));
579ad540459SPierre 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");
580636b9322SMatthew G. Knepley   }
581e04ae0b4SMatthew G. Knepley   if (localU && localU != localX) PetscCall(DMPlexInsertBoundaryValues(plex, PETSC_TRUE, localU, time, NULL, NULL, NULL));
582e04ae0b4SMatthew G. Knepley   PetscCall(DMGetCoordinateField(dm, &coordField));
583e04ae0b4SMatthew G. Knepley   /**** No collective calls below this point ****/
584636b9322SMatthew G. Knepley   /* Determine height for iteration of all meshes */
585636b9322SMatthew G. Knepley   {
586636b9322SMatthew G. Knepley     DMPolytopeType ct, ctIn, ctAux;
58719552267SMatthew G. Knepley     PetscInt       minHeightIn, minHeightAux, lStart, pStart, pEnd, p, pStartIn, pStartAux, pEndAux;
58819552267SMatthew G. Knepley     PetscInt       dim = -1, dimIn = -1, dimAux = -1;
58988aca1feSMatthew G. Knepley 
5909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSimplexOrBoxCells(plex, minHeight, &pStart, &pEnd));
591636b9322SMatthew G. Knepley     if (pEnd > pStart) {
5929566063dSJacob Faibussowitsch       PetscCall(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, minHeight, &lStart, NULL));
593636b9322SMatthew G. Knepley       p = lStart < 0 ? pStart : lStart;
5949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(plex, p, &ct));
595636b9322SMatthew G. Knepley       dim = DMPolytopeTypeGetDim(ct);
5969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetVTKCellHeight(plexIn, &minHeightIn));
5979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSimplexOrBoxCells(plexIn, minHeightIn, &pStartIn, NULL));
5989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(plexIn, pStartIn, &ctIn));
599636b9322SMatthew G. Knepley       dimIn = DMPolytopeTypeGetDim(ctIn);
600636b9322SMatthew G. Knepley       if (dmAux) {
6019566063dSJacob Faibussowitsch         PetscCall(DMPlexGetVTKCellHeight(plexAux, &minHeightAux));
60219552267SMatthew G. Knepley         PetscCall(DMPlexGetSimplexOrBoxCells(plexAux, minHeightAux, &pStartAux, &pEndAux));
60319552267SMatthew G. Knepley         if (pStartAux < pEndAux) {
6049566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(plexAux, pStartAux, &ctAux));
605636b9322SMatthew G. Knepley           dimAux = DMPolytopeTypeGetDim(ctAux);
60619552267SMatthew G. Knepley         }
607636b9322SMatthew G. Knepley       } else dimAux = dim;
608e04ae0b4SMatthew G. Knepley     } else {
609e04ae0b4SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
610e04ae0b4SMatthew G. Knepley       PetscCall(DMDestroy(&plexIn));
611e04ae0b4SMatthew G. Knepley       if (dmAux) PetscCall(DMDestroy(&plexAux));
612e04ae0b4SMatthew G. Knepley       PetscFunctionReturn(0);
613e39fcb4eSStefano Zampini     }
614636b9322SMatthew G. Knepley     if (dim < 0) {
615636b9322SMatthew G. Knepley       DMLabel spmap = NULL, spmapIn = NULL, spmapAux = NULL;
616636b9322SMatthew G. Knepley 
617636b9322SMatthew G. Knepley       /* Fall back to determination based on being a submesh */
6189566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSubpointMap(plex, &spmap));
6199566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSubpointMap(plexIn, &spmapIn));
6209566063dSJacob Faibussowitsch       if (plexAux) PetscCall(DMPlexGetSubpointMap(plexAux, &spmapAux));
621636b9322SMatthew G. Knepley       dim    = spmap ? 1 : 0;
622636b9322SMatthew G. Knepley       dimIn  = spmapIn ? 1 : 0;
623636b9322SMatthew G. Knepley       dimAux = spmapAux ? 1 : 0;
62488aca1feSMatthew G. Knepley     }
625636b9322SMatthew G. Knepley     {
62619552267SMatthew G. Knepley       PetscInt dimProj   = PetscMin(PetscMin(dim, dimIn), (dimAux < 0 ? PETSC_MAX_INT : dimAux));
62719552267SMatthew G. Knepley       PetscInt dimAuxEff = dimAux < 0 ? dimProj : dimAux;
628636b9322SMatthew G. Knepley 
62919552267SMatthew 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");
630636b9322SMatthew G. Knepley       if (dimProj < dim) minHeight = 1;
631636b9322SMatthew G. Knepley       htInc    = dim - dimProj;
632636b9322SMatthew G. Knepley       htIncIn  = dimIn - dimProj;
63319552267SMatthew G. Knepley       htIncAux = dimAuxEff - dimProj;
6340de51b56SMatthew G. Knepley     }
635a6e0b375SMatthew G. Knepley   }
6369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(plex, &depth));
6379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(plex, &depthLabel));
6389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(plex, &maxHeight));
6392af58022SMatthew G. Knepley   maxHeight = PetscMax(maxHeight, minHeight);
64063a3b9bcSJacob 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);
6419566063dSJacob Faibussowitsch   PetscCall(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, 0, NULL, &ds));
6429566063dSJacob Faibussowitsch   if (!ds) PetscCall(DMGetDS(dm, &ds));
6439566063dSJacob Faibussowitsch   PetscCall(DMGetFirstLabeledPoint(dmIn, dm, label, numIds, ids, 0, NULL, &dsIn));
6449566063dSJacob Faibussowitsch   if (!dsIn) PetscCall(DMGetDS(dmIn, &dsIn));
6459566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
6469566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(dsIn, &NfIn));
6479566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &NfTot));
6489566063dSJacob Faibussowitsch   PetscCall(DMFindRegionNum(dm, ds, &regionNum));
6499566063dSJacob Faibussowitsch   PetscCall(DMGetRegionNumDS(dm, regionNum, NULL, &fieldIS, NULL));
6509566063dSJacob Faibussowitsch   PetscCall(PetscDSIsCohesive(ds, &isCohesive));
6519566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
6529566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
6530c898c18SMatthew G. Knepley   if (dmAux) {
6549566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmAux, &dsAux));
6559566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(dsAux, &NfAux));
6560c898c18SMatthew G. Knepley   }
6579566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
6589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(Nf, &isFE, Nf, &sp, NfIn, &spIn));
6599566063dSJacob Faibussowitsch   if (maxHeight > 0) PetscCall(PetscMalloc2(Nf, &cellsp, NfIn, &cellspIn));
6609371c9d4SSatish Balay   else {
6619371c9d4SSatish Balay     cellsp   = sp;
6629371c9d4SSatish Balay     cellspIn = spIn;
6639371c9d4SSatish Balay   }
6648c6c5593SMatthew G. Knepley   /* Get cell dual spaces */
66547923291SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
666665f567fSMatthew G. Knepley     PetscDiscType disctype;
66747923291SMatthew G. Knepley 
6689566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscType_Internal(ds, f, &disctype));
669665f567fSMatthew G. Knepley     if (disctype == PETSC_DISC_FE) {
670665f567fSMatthew G. Knepley       PetscFE fe;
67147923291SMatthew G. Knepley 
67247923291SMatthew G. Knepley       isFE[f] = PETSC_TRUE;
673665f567fSMatthew G. Knepley       hasFE   = PETSC_TRUE;
6749566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, (PetscObject *)&fe));
6759566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace(fe, &cellsp[f]));
676665f567fSMatthew G. Knepley     } else if (disctype == PETSC_DISC_FV) {
677665f567fSMatthew G. Knepley       PetscFV fv;
67847923291SMatthew G. Knepley 
67947923291SMatthew G. Knepley       isFE[f] = PETSC_FALSE;
680665f567fSMatthew G. Knepley       hasFV   = PETSC_TRUE;
6819566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, (PetscObject *)&fv));
6829566063dSJacob Faibussowitsch       PetscCall(PetscFVGetDualSpace(fv, &cellsp[f]));
683665f567fSMatthew G. Knepley     } else {
684665f567fSMatthew G. Knepley       isFE[f]   = PETSC_FALSE;
685665f567fSMatthew G. Knepley       cellsp[f] = NULL;
686665f567fSMatthew G. Knepley     }
68747923291SMatthew G. Knepley   }
688636b9322SMatthew G. Knepley   for (f = 0; f < NfIn; ++f) {
689636b9322SMatthew G. Knepley     PetscDiscType disctype;
690636b9322SMatthew G. Knepley 
6919566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscType_Internal(dsIn, f, &disctype));
692636b9322SMatthew G. Knepley     if (disctype == PETSC_DISC_FE) {
693636b9322SMatthew G. Knepley       PetscFE fe;
694636b9322SMatthew G. Knepley 
6959566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsIn, f, (PetscObject *)&fe));
6969566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace(fe, &cellspIn[f]));
697636b9322SMatthew G. Knepley     } else if (disctype == PETSC_DISC_FV) {
698636b9322SMatthew G. Knepley       PetscFV fv;
699636b9322SMatthew G. Knepley 
7009566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsIn, f, (PetscObject *)&fv));
7019566063dSJacob Faibussowitsch       PetscCall(PetscFVGetDualSpace(fv, &cellspIn[f]));
702636b9322SMatthew G. Knepley     } else {
703636b9322SMatthew G. Knepley       cellspIn[f] = NULL;
704636b9322SMatthew G. Knepley     }
705636b9322SMatthew G. Knepley   }
706636b9322SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
7079371c9d4SSatish Balay     if (!htInc) {
7089371c9d4SSatish Balay       sp[f] = cellsp[f];
7099371c9d4SSatish Balay     } else PetscCall(PetscDualSpaceGetHeightSubspace(cellsp[f], htInc, &sp[f]));
710636b9322SMatthew G. Knepley   }
711ece3a9fcSMatthew G. Knepley   if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) {
71274fc349aSMatthew G. Knepley     PetscFE          fem, subfem;
713665f567fSMatthew G. Knepley     PetscDiscType    disctype;
7144a3e9fdbSToby Isaac     const PetscReal *points;
7154a3e9fdbSToby Isaac     PetscInt         numPoints;
7160c898c18SMatthew G. Knepley 
71708401ef6SPierre Jolivet     PetscCheck(maxHeight <= minHeight, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Field projection not supported for face interpolation");
7189566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceGetAllPointsUnion(Nf, sp, dim - htInc, funcs, &allPoints));
7199566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(allPoints, NULL, NULL, &numPoints, &points, NULL));
7209566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(NfIn, &T, NfAux, &TAux));
721a6e0b375SMatthew G. Knepley     for (f = 0; f < NfIn; ++f) {
7229371c9d4SSatish Balay       if (!htIncIn) {
7239371c9d4SSatish Balay         spIn[f] = cellspIn[f];
7249371c9d4SSatish Balay       } else PetscCall(PetscDualSpaceGetHeightSubspace(cellspIn[f], htIncIn, &spIn[f]));
725636b9322SMatthew G. Knepley 
7269566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscType_Internal(dsIn, f, &disctype));
727665f567fSMatthew G. Knepley       if (disctype != PETSC_DISC_FE) continue;
7289566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsIn, f, (PetscObject *)&fem));
7299371c9d4SSatish Balay       if (!htIncIn) {
7309371c9d4SSatish Balay         subfem = fem;
7319371c9d4SSatish Balay       } else PetscCall(PetscFEGetHeightSubspace(fem, htIncIn, &subfem));
7329566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &T[f]));
7330c898c18SMatthew G. Knepley     }
7340c898c18SMatthew G. Knepley     for (f = 0; f < NfAux; ++f) {
7359566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscType_Internal(dsAux, f, &disctype));
736665f567fSMatthew G. Knepley       if (disctype != PETSC_DISC_FE) continue;
7379566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(dsAux, f, (PetscObject *)&fem));
7389371c9d4SSatish Balay       if (!htIncAux) {
7399371c9d4SSatish Balay         subfem = fem;
7409371c9d4SSatish Balay       } else PetscCall(PetscFEGetHeightSubspace(fem, htIncAux, &subfem));
7419566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &TAux[f]));
7420c898c18SMatthew G. Knepley     }
7430c898c18SMatthew G. Knepley   }
74447923291SMatthew G. Knepley   /* Note: We make no attempt to optimize for height. Higher height things just overwrite the lower height results. */
7452af58022SMatthew G. Knepley   for (h = minHeight; h <= maxHeight; h++) {
746636b9322SMatthew G. Knepley     PetscInt     hEff     = h - minHeight + htInc;
747636b9322SMatthew G. Knepley     PetscInt     hEffIn   = h - minHeight + htIncIn;
748636b9322SMatthew G. Knepley     PetscInt     hEffAux  = h - minHeight + htIncAux;
749a6e0b375SMatthew G. Knepley     PetscDS      dsEff    = ds;
750636b9322SMatthew G. Knepley     PetscDS      dsEffIn  = dsIn;
751636b9322SMatthew G. Knepley     PetscDS      dsEffAux = dsAux;
7528c6c5593SMatthew G. Knepley     PetscScalar *values;
753b7260050SToby Isaac     PetscBool   *fieldActive;
754b7260050SToby Isaac     PetscInt     maxDegree;
755e5e52638SMatthew G. Knepley     PetscInt     pStart, pEnd, p, lStart, spDim, totDim, numValues;
756c330f8ffSToby Isaac     IS           heightIS;
7578c6c5593SMatthew G. Knepley 
758636b9322SMatthew G. Knepley     if (h > minHeight) {
7599566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDualSpaceGetHeightSubspace(cellsp[f], hEff, &sp[f]));
760636b9322SMatthew G. Knepley     }
7619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSimplexOrBoxCells(plex, h, &pStart, &pEnd));
7629566063dSJacob Faibussowitsch     PetscCall(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, h, &lStart, NULL));
7639566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(depthLabel, depth - h, &heightIS));
764c330f8ffSToby Isaac     if (pEnd <= pStart) {
7659566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&heightIS));
766c330f8ffSToby Isaac       continue;
767c330f8ffSToby Isaac     }
76847923291SMatthew G. Knepley     /* Compute totDim, the number of dofs in the closure of a point at this height */
76947923291SMatthew G. Knepley     totDim = 0;
77047923291SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
7715fedec97SMatthew G. Knepley       PetscBool cohesive;
7725fedec97SMatthew G. Knepley 
773665f567fSMatthew G. Knepley       if (!sp[f]) continue;
7749566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
7759566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceGetDimension(sp[f], &spDim));
7769c3cf19fSMatthew G. Knepley       totDim += spDim;
7775fedec97SMatthew G. Knepley       if (isCohesive && !cohesive) totDim += spDim;
77847923291SMatthew G. Knepley     }
779636b9322SMatthew G. Knepley     p = lStart < 0 ? pStart : lStart;
7809566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(plex, section, localX, p, &numValues, NULL));
78163a3b9bcSJacob 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);
782c330f8ffSToby Isaac     if (!totDim) {
7839566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&heightIS));
784c330f8ffSToby Isaac       continue;
785c330f8ffSToby Isaac     }
7869566063dSJacob Faibussowitsch     if (htInc) PetscCall(PetscDSGetHeightSubspace(ds, hEff, &dsEff));
787636b9322SMatthew G. Knepley     /* Compute totDimIn, the number of dofs in the closure of a point at this height */
788636b9322SMatthew G. Knepley     if (localU) {
789636b9322SMatthew G. Knepley       PetscInt totDimIn, pIn, numValuesIn;
790636b9322SMatthew G. Knepley 
791636b9322SMatthew G. Knepley       totDimIn = 0;
792636b9322SMatthew G. Knepley       for (f = 0; f < NfIn; ++f) {
7935fedec97SMatthew G. Knepley         PetscBool cohesive;
7945fedec97SMatthew G. Knepley 
795636b9322SMatthew G. Knepley         if (!spIn[f]) continue;
7969566063dSJacob Faibussowitsch         PetscCall(PetscDSGetCohesive(dsIn, f, &cohesive));
7979566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetDimension(spIn[f], &spDim));
798636b9322SMatthew G. Knepley         totDimIn += spDim;
7995fedec97SMatthew G. Knepley         if (isCohesive && !cohesive) totDimIn += spDim;
800636b9322SMatthew G. Knepley       }
8019566063dSJacob Faibussowitsch       PetscCall(DMGetEnclosurePoint(dmIn, dm, encIn, lStart < 0 ? pStart : lStart, &pIn));
8029566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(plexIn, NULL, localU, pIn, &numValuesIn, NULL));
80363a3b9bcSJacob Faibussowitsch       PetscCheck(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);
8049566063dSJacob Faibussowitsch       if (htIncIn) PetscCall(PetscDSGetHeightSubspace(dsIn, hEffIn, &dsEffIn));
805636b9322SMatthew G. Knepley     }
8069566063dSJacob Faibussowitsch     if (htIncAux) PetscCall(PetscDSGetHeightSubspace(dsAux, hEffAux, &dsEffAux));
80747923291SMatthew G. Knepley     /* Loop over points at this height */
8089566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numValues, MPIU_SCALAR, &values));
8099566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, NfTot, MPI_INT, &fieldActive));
810aa0eca99SMatthew G. Knepley     {
811aa0eca99SMatthew G. Knepley       const PetscInt *fields;
812aa0eca99SMatthew G. Knepley 
8139566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(fieldIS, &fields));
814ad540459SPierre Jolivet       for (f = 0; f < NfTot; ++f) fieldActive[f] = PETSC_FALSE;
815ad540459SPierre Jolivet       for (f = 0; f < Nf; ++f) fieldActive[fields[f]] = (funcs[f] && sp[f]) ? PETSC_TRUE : PETSC_FALSE;
8169566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(fieldIS, &fields));
817aa0eca99SMatthew G. Knepley     }
8188c6c5593SMatthew G. Knepley     if (label) {
8198c6c5593SMatthew G. Knepley       PetscInt i;
82047923291SMatthew G. Knepley 
82147923291SMatthew G. Knepley       for (i = 0; i < numIds; ++i) {
822c330f8ffSToby Isaac         IS              pointIS, isectIS;
82347923291SMatthew G. Knepley         const PetscInt *points;
8248c6c5593SMatthew G. Knepley         PetscInt        n;
825c330f8ffSToby Isaac         PetscFEGeom    *fegeom = NULL, *chunkgeom = NULL;
826c330f8ffSToby Isaac         PetscQuadrature quad = NULL;
82747923291SMatthew G. Knepley 
8289566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumIS(label, ids[i], &pointIS));
82947923291SMatthew G. Knepley         if (!pointIS) continue; /* No points with that id on this process */
8309566063dSJacob Faibussowitsch         PetscCall(ISIntersect(pointIS, heightIS, &isectIS));
8319566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&pointIS));
832c330f8ffSToby Isaac         if (!isectIS) continue;
8339566063dSJacob Faibussowitsch         PetscCall(ISGetLocalSize(isectIS, &n));
8349566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(isectIS, &points));
8359566063dSJacob Faibussowitsch         PetscCall(DMFieldGetDegree(coordField, isectIS, NULL, &maxDegree));
83648a46eb9SPierre Jolivet         if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, isectIS, &quad));
837c330f8ffSToby Isaac         if (!quad) {
838c330f8ffSToby Isaac           if (!h && allPoints) {
839c330f8ffSToby Isaac             quad      = allPoints;
840c330f8ffSToby Isaac             allPoints = NULL;
841c330f8ffSToby Isaac           } else {
8429566063dSJacob Faibussowitsch             PetscCall(PetscDualSpaceGetAllPointsUnion(Nf, sp, isCohesive ? dim - htInc - 1 : dim - htInc, funcs, &quad));
843c330f8ffSToby Isaac           }
844c330f8ffSToby Isaac         }
8459566063dSJacob Faibussowitsch         PetscCall(DMFieldCreateFEGeom(coordField, isectIS, quad, (htInc && h == minHeight) ? PETSC_TRUE : PETSC_FALSE, &fegeom));
84647923291SMatthew G. Knepley         for (p = 0; p < n; ++p) {
84747923291SMatthew G. Knepley           const PetscInt point = points[p];
84847923291SMatthew G. Knepley 
8499566063dSJacob Faibussowitsch           PetscCall(PetscArrayzero(values, numValues));
8509566063dSJacob Faibussowitsch           PetscCall(PetscFEGeomGetChunk(fegeom, p, p + 1, &chunkgeom));
8519566063dSJacob Faibussowitsch           PetscCall(DMPlexSetActivePoint(dm, point));
852d0609cedSBarry 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));
8539566063dSJacob Faibussowitsch           if (transform) PetscCall(DMPlexBasisTransformPoint_Internal(plex, tdm, tv, point, fieldActive, PETSC_FALSE, values));
8549566063dSJacob Faibussowitsch           PetscCall(DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, point, Ncc, comps, label, ids[i], values, mode));
85547923291SMatthew G. Knepley         }
8569566063dSJacob Faibussowitsch         PetscCall(PetscFEGeomRestoreChunk(fegeom, p, p + 1, &chunkgeom));
8579566063dSJacob Faibussowitsch         PetscCall(PetscFEGeomDestroy(&fegeom));
8589566063dSJacob Faibussowitsch         PetscCall(PetscQuadratureDestroy(&quad));
8599566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(isectIS, &points));
8609566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&isectIS));
86147923291SMatthew G. Knepley       }
8628c6c5593SMatthew G. Knepley     } else {
863c330f8ffSToby Isaac       PetscFEGeom    *fegeom = NULL, *chunkgeom = NULL;
864c330f8ffSToby Isaac       PetscQuadrature quad = NULL;
865c330f8ffSToby Isaac       IS              pointIS;
866c330f8ffSToby Isaac 
8679566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pointIS));
8689566063dSJacob Faibussowitsch       PetscCall(DMFieldGetDegree(coordField, pointIS, NULL, &maxDegree));
86948a46eb9SPierre Jolivet       if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, pointIS, &quad));
870c330f8ffSToby Isaac       if (!quad) {
871c330f8ffSToby Isaac         if (!h && allPoints) {
872c330f8ffSToby Isaac           quad      = allPoints;
873c330f8ffSToby Isaac           allPoints = NULL;
874c330f8ffSToby Isaac         } else {
8759566063dSJacob Faibussowitsch           PetscCall(PetscDualSpaceGetAllPointsUnion(Nf, sp, dim - htInc, funcs, &quad));
876c330f8ffSToby Isaac         }
877c330f8ffSToby Isaac       }
8789566063dSJacob Faibussowitsch       PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, (htInc && h == minHeight) ? PETSC_TRUE : PETSC_FALSE, &fegeom));
8798c6c5593SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
8809566063dSJacob Faibussowitsch         PetscCall(PetscArrayzero(values, numValues));
8819566063dSJacob Faibussowitsch         PetscCall(PetscFEGeomGetChunk(fegeom, p - pStart, p - pStart + 1, &chunkgeom));
8829566063dSJacob Faibussowitsch         PetscCall(DMPlexSetActivePoint(dm, p));
883d0609cedSBarry 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));
8849566063dSJacob Faibussowitsch         if (transform) PetscCall(DMPlexBasisTransformPoint_Internal(plex, tdm, tv, p, fieldActive, PETSC_FALSE, values));
8859566063dSJacob Faibussowitsch         PetscCall(DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, p, Ncc, comps, NULL, -1, values, mode));
8868c6c5593SMatthew G. Knepley       }
8879566063dSJacob Faibussowitsch       PetscCall(PetscFEGeomRestoreChunk(fegeom, p - pStart, pStart - p + 1, &chunkgeom));
8889566063dSJacob Faibussowitsch       PetscCall(PetscFEGeomDestroy(&fegeom));
8899566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureDestroy(&quad));
8909566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
8918c6c5593SMatthew G. Knepley     }
8929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&heightIS));
8939566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values));
8949566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive));
89547923291SMatthew G. Knepley   }
8968c6c5593SMatthew G. Knepley   /* Cleanup */
897ece3a9fcSMatthew G. Knepley   if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) {
8989566063dSJacob Faibussowitsch     for (f = 0; f < NfIn; ++f) PetscCall(PetscTabulationDestroy(&T[f]));
8999566063dSJacob Faibussowitsch     for (f = 0; f < NfAux; ++f) PetscCall(PetscTabulationDestroy(&TAux[f]));
9009566063dSJacob Faibussowitsch     PetscCall(PetscFree2(T, TAux));
9010c898c18SMatthew G. Knepley   }
9029566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&allPoints));
9039566063dSJacob Faibussowitsch   PetscCall(PetscFree3(isFE, sp, spIn));
9049566063dSJacob Faibussowitsch   if (maxHeight > 0) PetscCall(PetscFree2(cellsp, cellspIn));
9059566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
9069566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plexIn));
9079566063dSJacob Faibussowitsch   if (dmAux) PetscCall(DMDestroy(&plexAux));
9088c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
90947923291SMatthew G. Knepley }
9108c6c5593SMatthew G. Knepley 
911d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLocal_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
912d71ae5a4SJacob Faibussowitsch {
9138c6c5593SMatthew G. Knepley   PetscFunctionBegin;
9149566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, NULL, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL, (void (**)(void))funcs, ctxs, mode, localX));
9158c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
9168c6c5593SMatthew G. Knepley }
9178c6c5593SMatthew G. Knepley 
918d71ae5a4SJacob 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)
919d71ae5a4SJacob Faibussowitsch {
9208c6c5593SMatthew G. Knepley   PetscFunctionBegin;
9219566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, NULL, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL, (void (**)(void))funcs, ctxs, mode, localX));
92247923291SMatthew G. Knepley   PetscFunctionReturn(0);
92347923291SMatthew G. Knepley }
92447923291SMatthew G. Knepley 
925d71ae5a4SJacob 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)
926d71ae5a4SJacob Faibussowitsch {
92747923291SMatthew G. Knepley   PetscFunctionBegin;
9289566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, localU, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL_FIELD, (void (**)(void))funcs, NULL, mode, localX));
9298c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
93047923291SMatthew G. Knepley }
93147923291SMatthew G. Knepley 
932d71ae5a4SJacob 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)
933d71ae5a4SJacob Faibussowitsch {
9348c6c5593SMatthew G. Knepley   PetscFunctionBegin;
9359566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_FIELD, (void (**)(void))funcs, NULL, mode, localX));
93647923291SMatthew G. Knepley   PetscFunctionReturn(0);
93747923291SMatthew G. Knepley }
938ece3a9fcSMatthew G. Knepley 
939d71ae5a4SJacob 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)
940d71ae5a4SJacob Faibussowitsch {
941ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
9429566063dSJacob Faibussowitsch   PetscCall(DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_BD_FIELD, (void (**)(void))funcs, NULL, mode, localX));
943ece3a9fcSMatthew G. Knepley   PetscFunctionReturn(0);
944ece3a9fcSMatthew G. Knepley }
945