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