Actual source code: plexproject.c

petsc-3.10.5 2019-03-28
Report Typos and Errors
  1:  #include <petsc/private/dmpleximpl.h>

  3:  #include <petsc/private/petscfeimpl.h>

  5: static PetscErrorCode DMProjectPoint_Func_Private(DM dm, PetscDS prob, PetscReal time, PetscFEGeom *fegeom, PetscFVCellGeom *fvgeom, PetscBool isFE[], PetscDualSpace sp[],
  6:                                                   PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs,
  7:                                                   PetscScalar values[])
  8: {
  9:   PetscInt       coordDim, Nf, *Nc, f, totDim, spDim, d, v, tp;
 10:   PetscBool      isAffine;

 14:   DMGetCoordinateDim(dm,&coordDim);
 15:   PetscDSGetNumFields(prob, &Nf);
 16:   PetscDSGetComponents(prob, &Nc);
 17:   PetscDSGetTotalDimension(prob, &totDim);
 18:   /* Get values for closure */
 19:   isAffine = fegeom->isAffine;
 20:   for (f = 0, v = 0, tp = 0; f < Nf; ++f) {
 21:     void * const ctx = ctxs ? ctxs[f] : NULL;

 23:     if (!sp[f]) continue;
 24:     PetscDualSpaceGetDimension(sp[f], &spDim);
 25:     if (funcs[f]) {
 26:       if (isFE[f]) {
 27:         PetscQuadrature   allPoints;
 28:         PetscInt          q, dim, numPoints;
 29:         const PetscReal   *points;
 30:         PetscScalar       *pointEval;
 31:         PetscReal         *x;
 32:         DM                dm;

 34:         PetscDualSpaceGetDM(sp[f],&dm);
 35:         PetscDualSpaceGetAllPoints(sp[f], &allPoints);
 36:         PetscQuadratureGetData(allPoints,&dim,NULL,&numPoints,&points,NULL);
 37:         PetscDualSpaceGetDM(sp[f],&dm);
 38:         DMGetWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval);
 39:         DMGetWorkArray(dm,coordDim,MPIU_REAL,&x);
 40:         for (q = 0; q < numPoints; q++, tp++) {
 41:           const PetscReal *v0;

 43:           if (isAffine) {
 44:             CoordinatesRefToReal(coordDim, fegeom->dim, fegeom->xi, fegeom->v, fegeom->J, &points[q*dim], x);
 45:             v0 = x;
 46:           } else {
 47:             v0 = &fegeom->v[tp*coordDim];
 48:           }
 49:           (*funcs[f])(coordDim,time,v0, Nc[f], &pointEval[Nc[f]*q], ctx);
 50:         }
 51:         PetscDualSpaceApplyAll(sp[f], pointEval, &values[v]);
 52:         DMRestoreWorkArray(dm,coordDim,MPIU_REAL,&x);
 53:         DMRestoreWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval);
 54:         v += spDim;
 55:       } else {
 56:         for (d = 0; d < spDim; ++d, ++v) {
 57:           PetscDualSpaceApplyFVM(sp[f], d, time, fvgeom, Nc[f], funcs[f], ctx, &values[v]);
 58:         }
 59:       }
 60:     } else {
 61:       for (d = 0; d < spDim; d++, v++) {values[v] = 0.0;}
 62:     }
 63:   }
 64:   return(0);
 65: }

 67: static PetscErrorCode DMProjectPoint_Field_Private(DM dm, PetscDS prob, DM dmAux, PetscDS probAux, PetscReal time, Vec localU, Vec localA, PetscFEGeom *fegeom, PetscDualSpace sp[], PetscInt p, PetscInt Ncc, const PetscInt comps[],
 68:                                                    PetscReal **basisTab, PetscReal **basisDerTab, PetscReal **basisTabAux, PetscReal **basisDerTabAux,
 69:                                                    void (**funcs)(PetscInt, PetscInt, PetscInt,
 70:                                                                   const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
 71:                                                                   const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
 72:                                                                   PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), void **ctxs,
 73:                                                    PetscScalar values[])
 74: {
 75:   PetscSection       section, sectionAux = NULL;
 76:   PetscScalar       *u, *u_t = NULL, *u_x, *a = NULL, *a_t = NULL, *a_x = NULL, *refSpaceDer, *refSpaceDerAux = NULL, *bc;
 77:   PetscScalar       *coefficients   = NULL, *coefficientsAux   = NULL;
 78:   PetscScalar       *coefficients_t = NULL, *coefficientsAux_t = NULL;
 79:   const PetscScalar *constants;
 80:   PetscReal         *x;
 81:   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nb, *Nc, *NbAux = NULL, *NcAux = NULL;
 82:   const PetscInt     dE = fegeom->dimEmbed;
 83:   PetscInt           dimAux = 0, numConstants, Nf, NfAux = 0, f, spDim, d, v, tp = 0;
 84:   PetscBool          isAffine;
 85:   PetscErrorCode     ierr;

 88:   PetscDSGetNumFields(prob, &Nf);
 89:   PetscDSGetDimensions(prob, &Nb);
 90:   PetscDSGetComponents(prob, &Nc);
 91:   PetscDSGetComponentOffsets(prob, &uOff);
 92:   PetscDSGetComponentDerivativeOffsets(prob, &uOff_x);
 93:   PetscDSGetEvaluationArrays(prob, &u, &bc /*&u_t*/, &u_x);
 94:   PetscDSGetRefCoordArrays(prob, &x, &refSpaceDer);
 95:   PetscDSGetConstants(prob, &numConstants, &constants);
 96:   DMGetSection(dm, &section);
 97:   DMPlexVecGetClosure(dm, section, localU, p, NULL, &coefficients);
 98:   if (dmAux) {
 99:     DMLabel  spmap;
100:     PetscInt subp = p;

102:     /* If dm is a submesh, do not get subpoint */
103:     DMPlexGetSubpointMap(dm, &spmap);
104:     if (!spmap) {DMPlexGetSubpoint(dmAux, p, &subp);}
105:     PetscDSGetSpatialDimension(probAux, &dimAux);
106:     PetscDSGetNumFields(probAux, &NfAux);
107:     PetscDSGetDimensions(probAux, &NbAux);
108:     PetscDSGetComponents(probAux, &NcAux);
109:     DMGetSection(dmAux, &sectionAux);
110:     PetscDSGetComponentOffsets(probAux, &aOff);
111:     PetscDSGetComponentDerivativeOffsets(probAux, &aOff_x);
112:     PetscDSGetEvaluationArrays(probAux, &a, NULL /*&a_t*/, &a_x);
113:     PetscDSGetRefCoordArrays(probAux, NULL, &refSpaceDerAux);
114:     DMPlexVecGetClosure(dmAux, sectionAux, localA, subp, NULL, &coefficientsAux);
115:   }
116:   /* Get values for closure */
117:   isAffine = fegeom->isAffine;
118:   for (f = 0, v = 0; f < Nf; ++f) {
119:     PetscQuadrature   allPoints;
120:     PetscInt          q, dim, numPoints;
121:     const PetscReal   *points;
122:     PetscScalar       *pointEval;
123:     DM                dm;

125:     if (!sp[f]) continue;
126:     PetscDualSpaceGetDimension(sp[f], &spDim);
127:     if (!funcs[f]) {
128:       for (d = 0; d < spDim; d++, v++) values[v] = 0.;
129:       continue;
130:     }
131:     PetscDualSpaceGetDM(sp[f],&dm);
132:     PetscDualSpaceGetAllPoints(sp[f], &allPoints);
133:     PetscQuadratureGetData(allPoints,&dim,NULL,&numPoints,&points,NULL);
134:     DMGetWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval);
135:     for (q = 0; q < numPoints; ++q, ++tp) {
136:       const PetscReal *v0;
137:       const PetscReal *invJ;

139:       if (isAffine) {
140:         CoordinatesRefToReal(dE, dim, fegeom->xi, fegeom->v, fegeom->J, &points[q*dim], x);
141:         v0 = x;
142:         invJ = fegeom->invJ;
143:       } else {
144:         v0 = &fegeom->v[tp*dE];
145:         invJ = &fegeom->invJ[tp*dE*dE];
146:       }
147:       EvaluateFieldJets(dim, Nf, Nb, Nc, tp, basisTab, basisDerTab, refSpaceDer, invJ, coefficients, coefficients_t, u, u_x, u_t);
148:       if (probAux) {EvaluateFieldJets(dimAux, NfAux, NbAux, NcAux, tp, basisTabAux, basisDerTabAux, refSpaceDerAux, invJ, coefficientsAux, coefficientsAux_t, a, a_x, a_t);}
149:       (*funcs[f])(dE, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, time, v0, numConstants, constants, &pointEval[Nc[f]*q]);
150:     }
151:     PetscDualSpaceApplyAll(sp[f], pointEval, &values[v]);
152:     DMRestoreWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval);
153:     v += spDim;
154:   }
155:   DMPlexVecRestoreClosure(dm, section, localU, p, NULL, &coefficients);
156:   if (dmAux) {DMPlexVecRestoreClosure(dmAux, sectionAux, localA, p, NULL, &coefficientsAux);}
157:   return(0);
158: }

160: static PetscErrorCode DMProjectPoint_Private(DM dm, PetscDS prob, PetscFEGeom *fegeom, DM dmAux, PetscDS probAux, PetscInt effectiveHeight, PetscReal time, Vec localU, Vec localA, PetscBool hasFE, PetscBool hasFV, PetscBool isFE[],
161:                                              PetscDualSpace sp[], PetscInt p, PetscInt Ncc, const PetscInt comps[],
162:                                              PetscReal **basisTab, PetscReal **basisDerTab, PetscReal **basisTabAux, PetscReal **basisDerTabAux,
163:                                              DMBoundaryConditionType type, void (**funcs)(void), void **ctxs, PetscBool fieldActive[], PetscScalar values[])
164: {
165:   PetscFVCellGeom fvgeom;
166:   PetscInt        dim, dimEmbed;
167:   PetscErrorCode  ierr;

170:   DMGetDimension(dm, &dim);
171:   DMGetCoordinateDim(dm, &dimEmbed);
172:   if (hasFV) {DMPlexComputeCellGeometryFVM(dm, p, &fvgeom.volume, fvgeom.centroid, NULL);}
173:   switch (type) {
174:   case DM_BC_ESSENTIAL:
175:   case DM_BC_NATURAL:
176:     DMProjectPoint_Func_Private(dm, prob, time, fegeom, &fvgeom, isFE, sp, (PetscErrorCode (**)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *)) funcs, ctxs, values);break;
177:   case DM_BC_ESSENTIAL_FIELD:
178:   case DM_BC_NATURAL_FIELD:
179:     DMProjectPoint_Field_Private(dm, prob, dmAux, probAux, time, localU, localA, fegeom, sp, p, Ncc, comps,
180:                                         basisTab, basisDerTab, basisTabAux, basisDerTabAux,
181:                                         (void (**)(PetscInt, PetscInt, PetscInt,
182:                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
183:                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
184:                                                    PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[])) funcs, ctxs, values);break;
185:   default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown boundary condition type: %d", (int) type);
186:   }
187:   return(0);
188: }

190: static PetscErrorCode PetscDualSpaceGetAllPointsUnion(PetscInt Nf, PetscDualSpace *sp, PetscInt dim, void (**funcs)(void), PetscQuadrature *allPoints)
191: {
192:   PetscReal      *points;
193:   PetscInt       f, numPoints;

197:   numPoints = 0;
198:   for (f = 0; f < Nf; ++f) {
199:     if (funcs[f]) {
200:       PetscQuadrature fAllPoints;
201:       PetscInt        fNumPoints;

203:       PetscDualSpaceGetAllPoints(sp[f],&fAllPoints);
204:       PetscQuadratureGetData(fAllPoints, NULL, NULL, &fNumPoints, NULL, NULL);
205:       numPoints += fNumPoints;
206:     }
207:   }
208:   PetscMalloc1(dim*numPoints,&points);
209:   numPoints = 0;
210:   for (f = 0; f < Nf; ++f) {
211:     PetscInt spDim;

213:     PetscDualSpaceGetDimension(sp[f], &spDim);
214:     if (funcs[f]) {
215:       PetscQuadrature fAllPoints;
216:       PetscInt        qdim, fNumPoints, q;
217:       const PetscReal *fPoints;

219:       PetscDualSpaceGetAllPoints(sp[f],&fAllPoints);
220:       PetscQuadratureGetData(fAllPoints, &qdim, NULL, &fNumPoints, &fPoints, NULL);
221:       if (qdim != dim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Spatial dimension %D for dual basis does not match input dimension %D", qdim, dim);
222:       for (q = 0; q < fNumPoints*dim; ++q) points[numPoints*dim+q] = fPoints[q];
223:       numPoints += fNumPoints;
224:     }
225:   }
226:   PetscQuadratureCreate(PETSC_COMM_SELF,allPoints);
227:   PetscQuadratureSetData(*allPoints,dim,0,numPoints,points,NULL);
228:   return(0);
229: }

231: /*
232:   This function iterates over a manifold, and interpolates the input function/field using the basis provided by the DS in our DM

234:   There are several different scenarios:

236:   1) Volumetric mesh with volumetric auxiliary data

238:      Here minHeight=0 since we loop over cells.

240:   2) Boundary mesh with boundary auxiliary data

242:      Here minHeight=1 since we loop over faces. This normally happens since we hang cells off of our boundary meshes to facilitate computation.

244:   3) Volumetric mesh with boundary auxiliary data

246:      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.

248:   The maxHeight is used to support enforcement of constraints in DMForest.

250:   If localU is given and not equal to localX, we call DMPlexInsertBoundaryValues() to complete it.

252:   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.
253:     - 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
254:       is for the volumetric mesh, but we are iterating over a surface, then the effective height is nonzero. When th effective height is nonzero, we need to extract
255:       dual spaces for the boundary from our input spaces.
256:     - After extracting all quadrature points, we tabulate the input fields and auxiliary fields on them.

258:   We check that the #dof(closure(p)) == #dual basis functionals(p) for a representative p in the iteration

260:   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.
261: */
262: static PetscErrorCode DMProjectLocal_Generic_Plex(DM dm, PetscReal time, Vec localU,
263:                                                   PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt numIds, const PetscInt ids[],
264:                                                   DMBoundaryConditionType type, void (**funcs)(void), void **ctxs,
265:                                                   InsertMode mode, Vec localX)
266: {
267:   DM              dmAux = NULL;
268:   PetscDS         prob, probAux = NULL;
269:   Vec             localA = NULL;
270:   PetscSection    section;
271:   PetscDualSpace *sp, *cellsp;
272:   PetscReal     **basisTab = NULL, **basisDerTab = NULL, **basisTabAux = NULL, **basisDerTabAux = NULL;
273:   PetscInt       *Nc;
274:   PetscInt        dim, dimEmbed, depth, minHeight, maxHeight, h, Nf, NfAux = 0, f;
275:   PetscBool      *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE, auxBd = PETSC_FALSE;
276:   DMField         coordField;
277:   DMLabel         depthLabel;
278:   PetscQuadrature allPoints = NULL;
279:   PetscErrorCode  ierr;

282:   PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);
283:   PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &localA);
284:   DMGetDimension(dm, &dim);
285:   DMPlexGetVTKCellHeight(dm, &minHeight);
286:   /* Auxiliary information can only be used with interpolation of field functions */
287:   if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_NATURAL_FIELD) {
288:     if (!minHeight && dmAux) {
289:       DMLabel spmap;

291:       /* If dmAux is a surface, then force the projection to take place over a surface */
292:       DMPlexGetSubpointMap(dmAux, &spmap);
293:       if (spmap) {minHeight = 1; auxBd = PETSC_TRUE;}
294:     }
295:   }
296:   DMPlexGetMaxProjectionHeight(dm, &maxHeight);
297:   maxHeight = PetscMax(maxHeight, minHeight);
298:   if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Maximum projection height %d not in [0, %d)\n", maxHeight, dim);}
299:   DMGetDS(dm, &prob);
300:   DMGetCoordinateDim(dm, &dimEmbed);
301:   DMGetSection(dm, &section);
302:   PetscSectionGetNumFields(section, &Nf);
303:   if (dmAux) {
304:     DMGetDS(dmAux, &probAux);
305:     PetscDSGetNumFields(probAux, &NfAux);
306:   }
307:   PetscDSGetComponents(prob, &Nc);
308:   PetscMalloc2(Nf, &isFE, Nf, &sp);
309:   if (maxHeight > 0) {PetscMalloc1(Nf, &cellsp);}
310:   else               {cellsp = sp;}
311:   if (localU && localU != localX) {DMPlexInsertBoundaryValues(dm, PETSC_TRUE, localU, time, NULL, NULL, NULL);}
312:   /* Get cell dual spaces */
313:   for (f = 0; f < Nf; ++f) {
314:     PetscObject  obj;
315:     PetscClassId id;

317:     DMGetField(dm, f, &obj);
318:     PetscObjectGetClassId(obj, &id);
319:     if (id == PETSCFE_CLASSID) {
320:       PetscFE fe = (PetscFE) obj;

322:       hasFE   = PETSC_TRUE;
323:       isFE[f] = PETSC_TRUE;
324:       PetscFEGetDualSpace(fe, &cellsp[f]);
325:     } else if (id == PETSCFV_CLASSID) {
326:       PetscFV fv = (PetscFV) obj;

328:       hasFV   = PETSC_TRUE;
329:       isFE[f] = PETSC_FALSE;
330:       PetscFVGetDualSpace(fv, &cellsp[f]);
331:     } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
332:   }
333:   DMGetCoordinateField(dm,&coordField);
334:   if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_NATURAL_FIELD) {
335:     PetscInt         effectiveHeight = auxBd ? minHeight : 0;
336:     PetscFE          fem, subfem;
337:     const PetscReal *points;
338:     PetscInt         numPoints;

340:     if (maxHeight > minHeight) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Field projection not supported for face interpolation");
341:     for (f = 0; f < Nf; ++f) {
342:       if (!effectiveHeight) {sp[f] = cellsp[f];}
343:       else                  {PetscDualSpaceGetHeightSubspace(cellsp[f], effectiveHeight, &sp[f]);}
344:     }
345:     PetscDualSpaceGetAllPointsUnion(Nf,sp,dim-effectiveHeight,funcs,&allPoints);
346:     PetscQuadratureGetData(allPoints,NULL,NULL,&numPoints,&points,NULL);
347:     PetscMalloc4(Nf, &basisTab, Nf, &basisDerTab, NfAux, &basisTabAux, NfAux, &basisDerTabAux);
348:     for (f = 0; f < Nf; ++f) {
349:       if (!isFE[f]) continue;
350:       PetscDSGetDiscretization(prob, f, (PetscObject *) &fem);
351:       if (!effectiveHeight) {subfem = fem;}
352:       else                  {PetscFEGetHeightSubspace(fem, effectiveHeight, &subfem);}
353:       PetscFEGetTabulation(subfem, numPoints, points, &basisTab[f], &basisDerTab[f], NULL);
354:     }
355:     for (f = 0; f < NfAux; ++f) {
356:       PetscDSGetDiscretization(probAux, f, (PetscObject *) &fem);
357:       if (!effectiveHeight || auxBd) {subfem = fem;}
358:       else                           {PetscFEGetHeightSubspace(fem, effectiveHeight, &subfem);}
359:       PetscFEGetTabulation(subfem, numPoints, points, &basisTabAux[f], &basisDerTabAux[f], NULL);
360:     }
361:   }
362:   DMPlexGetDepth(dm,&depth);
363:   DMPlexGetDepthLabel(dm,&depthLabel);
364:   /* Note: We make no attempt to optimize for height. Higher height things just overwrite the lower height results. */
365:   for (h = minHeight; h <= maxHeight; h++) {
366:     PetscInt     effectiveHeight = h - (auxBd ? 0 : minHeight);
367:     PetscDS      probEff         = prob;
368:     PetscScalar *values;
369:     PetscBool   *fieldActive;
370:     PetscInt     maxDegree;
371:     PetscInt     pStart, pEnd, p, spDim, totDim, numValues;
372:     IS           heightIS;

374:     if (effectiveHeight) {PetscDSGetHeightSubspace(prob, effectiveHeight, &probEff);}
375:     DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);
376:     DMLabelGetStratumIS(depthLabel,depth - h,&heightIS);
377:     if (!h) {
378:       PetscInt cEndInterior;

380:       DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);
381:       pEnd = cEndInterior < 0 ? pEnd : cEndInterior;
382:     }
383:     if (pEnd <= pStart) {
384:       ISDestroy(&heightIS);
385:       continue;
386:     }
387:     /* Compute totDim, the number of dofs in the closure of a point at this height */
388:     totDim = 0;
389:     for (f = 0; f < Nf; ++f) {
390:       if (!effectiveHeight) {
391:         sp[f] = cellsp[f];
392:       } else {
393:         PetscDualSpaceGetHeightSubspace(cellsp[f], effectiveHeight, &sp[f]);
394:         if (!sp[f]) continue;
395:       }
396:       PetscDualSpaceGetDimension(sp[f], &spDim);
397:       totDim += spDim;
398:     }
399:     DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);
400:     if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The section point closure size %d != dual space dimension %d", numValues, totDim);
401:     if (!totDim) {
402:       ISDestroy(&heightIS);
403:       continue;
404:     }
405:     /* Loop over points at this height */
406:     DMGetWorkArray(dm, numValues, MPIU_SCALAR, &values);
407:     DMGetWorkArray(dm, Nf, MPI_INT, &fieldActive);
408:     for (f = 0; f < Nf; ++f) fieldActive[f] = (funcs[f] && sp[f]) ? PETSC_TRUE : PETSC_FALSE;
409:     if (label) {
410:       PetscInt i;

412:       for (i = 0; i < numIds; ++i) {
413:         IS              pointIS, isectIS;
414:         const PetscInt *points;
415:         PetscInt        n;
416:         PetscFEGeom  *fegeom = NULL, *chunkgeom = NULL;
417:         PetscQuadrature quad = NULL;

419:         DMLabelGetStratumIS(label, ids[i], &pointIS);
420:         if (!pointIS) continue; /* No points with that id on this process */
421:         ISIntersect(pointIS,heightIS,&isectIS);
422:         ISDestroy(&pointIS);
423:         if (!isectIS) continue;
424:         ISGetLocalSize(isectIS, &n);
425:         ISGetIndices(isectIS, &points);
426:         DMFieldGetDegree(coordField,isectIS,NULL,&maxDegree);
427:         if (maxDegree <= 1) {
428:           DMFieldCreateDefaultQuadrature(coordField,isectIS,&quad);
429:         }
430:         if (!quad) {
431:           if (!h && allPoints) {
432:             quad = allPoints;
433:             allPoints = NULL;
434:           } else {
435:             PetscDualSpaceGetAllPointsUnion(Nf,sp,dim-h,funcs,&quad);
436:           }
437:         }
438:         DMFieldCreateFEGeom(coordField,isectIS,quad,PETSC_FALSE,&fegeom);
439:         for (p = 0; p < n; ++p) {
440:           const PetscInt  point = points[p];

442:           PetscMemzero(values, numValues * sizeof(PetscScalar));
443:           PetscFEGeomGetChunk(fegeom,p,p+1,&chunkgeom);
444:           DMProjectPoint_Private(dm, probEff, chunkgeom, dmAux, probAux, effectiveHeight, time, localU, localA, hasFE, hasFV, isFE, sp, point, Ncc, comps, basisTab, basisDerTab, basisTabAux, basisDerTabAux, type, funcs, ctxs, fieldActive, values);
445:           if (ierr) {
446:             PetscErrorCode ierr2;
447:             ierr2 = DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values);CHKERRQ(ierr2);
448:             ierr2 = DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive);CHKERRQ(ierr2);
449: 
450:           }
451:           DMPlexVecSetFieldClosure_Internal(dm, section, localX, fieldActive, point, Ncc, comps, values, mode);
452:         }
453:         PetscFEGeomRestoreChunk(fegeom,p,p+1,&chunkgeom);
454:         PetscFEGeomDestroy(&fegeom);
455:         PetscQuadratureDestroy(&quad);
456:         ISRestoreIndices(isectIS, &points);
457:         ISDestroy(&isectIS);
458:       }
459:     } else {
460:       PetscFEGeom    *fegeom = NULL, *chunkgeom = NULL;
461:       PetscQuadrature quad = NULL;
462:       IS              pointIS;

464:       ISCreateStride(PETSC_COMM_SELF,pEnd-pStart,pStart,1,&pointIS);
465:       DMFieldGetDegree(coordField,pointIS,NULL,&maxDegree);
466:       if (maxDegree <= 1) {
467:         DMFieldCreateDefaultQuadrature(coordField,pointIS,&quad);
468:       }
469:       if (!quad) {
470:         if (!h && allPoints) {
471:           quad = allPoints;
472:           allPoints = NULL;
473:         } else {
474:           PetscDualSpaceGetAllPointsUnion(Nf,sp,dim-h,funcs,&quad);
475:         }
476:       }
477:       DMFieldCreateFEGeom(coordField,pointIS,quad,PETSC_FALSE,&fegeom);
478:       for (p = pStart; p < pEnd; ++p) {
479:         PetscMemzero(values, numValues * sizeof(PetscScalar));
480:         PetscFEGeomGetChunk(fegeom,p-pStart,p-pStart+1,&chunkgeom);
481:         DMProjectPoint_Private(dm, probEff, chunkgeom, dmAux, probAux, effectiveHeight, time, localU, localA, hasFE, hasFV, isFE, sp, p, Ncc, comps, basisTab, basisDerTab, basisTabAux, basisDerTabAux, type, funcs, ctxs, fieldActive, values);
482:         if (ierr) {
483:           PetscErrorCode ierr2;
484:           ierr2 = DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values);CHKERRQ(ierr2);
485:           ierr2 = DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive);CHKERRQ(ierr2);
486: 
487:         }
488:         DMPlexVecSetFieldClosure_Internal(dm, section, localX, fieldActive, p, Ncc, comps, values, mode);
489:       }
490:       PetscFEGeomRestoreChunk(fegeom,p-pStart,pStart-p+1,&chunkgeom);
491:       PetscFEGeomDestroy(&fegeom);
492:       PetscQuadratureDestroy(&quad);
493:       ISDestroy(&pointIS);
494:     }
495:     ISDestroy(&heightIS);
496:     DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values);
497:     DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive);
498:   }
499:   /* Cleanup */
500:   if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_NATURAL_FIELD) {
501:     PetscInt effectiveHeight = auxBd ? minHeight : 0;
502:     PetscFE  fem, subfem;

504:     for (f = 0; f < Nf; ++f) {
505:       if (!isFE[f]) continue;
506:       PetscDSGetDiscretization(prob, f, (PetscObject *) &fem);
507:       if (!effectiveHeight) {subfem = fem;}
508:       else                  {PetscFEGetHeightSubspace(fem, effectiveHeight, &subfem);}
509:       PetscFERestoreTabulation(subfem, 0, NULL, &basisTab[f], &basisDerTab[f], NULL);
510:     }
511:     for (f = 0; f < NfAux; ++f) {
512:       PetscDSGetDiscretization(probAux, f, (PetscObject *) &fem);
513:       if (!effectiveHeight || auxBd) {subfem = fem;}
514:       else                           {PetscFEGetHeightSubspace(fem, effectiveHeight, &subfem);}
515:       PetscFERestoreTabulation(subfem, 0, NULL, &basisTabAux[f], &basisDerTabAux[f], NULL);
516:     }
517:     PetscFree4(basisTab, basisDerTab, basisTabAux, basisDerTabAux);
518:   }
519:   PetscQuadratureDestroy(&allPoints);
520:   PetscFree2(isFE, sp);
521:   if (maxHeight > 0) {PetscFree(cellsp);}
522:   return(0);
523: }

525: PetscErrorCode DMProjectFunctionLocal_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
526: {

530:   DMProjectLocal_Generic_Plex(dm, time, localX, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL, (void (**)(void)) funcs, ctxs, mode, localX);
531:   return(0);
532: }

534: 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)
535: {

539:   DMProjectLocal_Generic_Plex(dm, time, localX, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL, (void (**)(void)) funcs, ctxs, mode, localX);
540:   return(0);
541: }

543: PetscErrorCode DMProjectFieldLocal_Plex(DM dm, PetscReal time, Vec localU,
544:                                         void (**funcs)(PetscInt, PetscInt, PetscInt,
545:                                                        const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
546:                                                        const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
547:                                                        PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
548:                                         InsertMode mode, Vec localX)
549: {

553:   DMProjectLocal_Generic_Plex(dm, time, localU, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL_FIELD, (void (**)(void)) funcs, NULL, mode, localX);
554:   return(0);
555: }

557: PetscErrorCode DMProjectFieldLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], Vec localU,
558:                                              void (**funcs)(PetscInt, PetscInt, PetscInt,
559:                                                             const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
560:                                                             const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
561:                                                             PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
562:                                              InsertMode mode, Vec localX)
563: {

567:   DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_FIELD, (void (**)(void)) funcs, NULL, mode, localX);
568:   return(0);
569: }