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, §ion)); 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, §ionAux)); 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, §ion)); 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, §ionAux)); 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, ®ionNum)); 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, §ion)); 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