xref: /petsc/src/snes/utils/dmplexsnes.c (revision 2cf2a4037edc21d5c05f749db82f170038eb1275)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I "petscdmplex.h" I*/
2af0996ceSBarry Smith #include <petsc/private/snesimpl.h>     /*I "petscsnes.h"   I*/
324cdb843SMatthew G. Knepley #include <petscds.h>
4a925c78cSMatthew G. Knepley #include <petscblaslapack.h>
5af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
6af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h>
7552f7358SJed Brown 
89044fa66SMatthew G. Knepley static PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
99044fa66SMatthew G. Knepley {
109044fa66SMatthew G. Knepley   PetscInt       numCells, step = 1;
119044fa66SMatthew G. Knepley   PetscBool      isStride;
129044fa66SMatthew G. Knepley   PetscErrorCode ierr;
139044fa66SMatthew G. Knepley 
149044fa66SMatthew G. Knepley   PetscFunctionBeginHot;
159044fa66SMatthew G. Knepley   *pStart = 0;
169044fa66SMatthew G. Knepley   *points = NULL;
179044fa66SMatthew G. Knepley   ierr = ISGetLocalSize(pointIS, &numCells);CHKERRQ(ierr);
189044fa66SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr);
199044fa66SMatthew G. Knepley   if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);}
209044fa66SMatthew G. Knepley   *pEnd   = *pStart + numCells;
219044fa66SMatthew G. Knepley   if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);}
229044fa66SMatthew G. Knepley   PetscFunctionReturn(0);
239044fa66SMatthew G. Knepley }
249044fa66SMatthew G. Knepley 
259044fa66SMatthew G. Knepley static PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
269044fa66SMatthew G. Knepley {
279044fa66SMatthew G. Knepley   PetscInt       step = 1;
289044fa66SMatthew G. Knepley   PetscBool      isStride;
299044fa66SMatthew G. Knepley   PetscErrorCode ierr;
309044fa66SMatthew G. Knepley 
319044fa66SMatthew G. Knepley   PetscFunctionBeginHot;
329044fa66SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr);
339044fa66SMatthew G. Knepley   if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);}
349044fa66SMatthew G. Knepley   if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);}
359044fa66SMatthew G. Knepley   PetscFunctionReturn(0);
369044fa66SMatthew G. Knepley }
379044fa66SMatthew G. Knepley 
389044fa66SMatthew G. Knepley static PetscErrorCode ISGetPointSubrange(IS subpointIS, PetscInt pStart, PetscInt pEnd, const PetscInt *points)
399044fa66SMatthew G. Knepley {
409044fa66SMatthew G. Knepley   PetscErrorCode ierr;
419044fa66SMatthew G. Knepley 
429044fa66SMatthew G. Knepley   PetscFunctionBeginHot;
439044fa66SMatthew G. Knepley   if (points) {
449044fa66SMatthew G. Knepley     ierr = ISSetType(subpointIS, ISGENERAL);CHKERRQ(ierr);
459044fa66SMatthew G. Knepley     ierr = ISGeneralSetIndices(subpointIS, pEnd-pStart, &points[pStart], PETSC_USE_POINTER);CHKERRQ(ierr);
469044fa66SMatthew G. Knepley   } else {
479044fa66SMatthew G. Knepley     ierr = ISSetType(subpointIS, ISSTRIDE);CHKERRQ(ierr);
489044fa66SMatthew G. Knepley     ierr = ISStrideSetStride(subpointIS, pEnd-pStart, pStart, 1);CHKERRQ(ierr);
499044fa66SMatthew G. Knepley   }
509044fa66SMatthew G. Knepley   PetscFunctionReturn(0);
519044fa66SMatthew G. Knepley }
529044fa66SMatthew G. Knepley 
5324cdb843SMatthew G. Knepley /************************** Interpolation *******************************/
5424cdb843SMatthew G. Knepley 
556da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy)
566da023fcSToby Isaac {
576da023fcSToby Isaac   PetscBool      isPlex;
586da023fcSToby Isaac   PetscErrorCode ierr;
596da023fcSToby Isaac 
606da023fcSToby Isaac   PetscFunctionBegin;
616da023fcSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr);
626da023fcSToby Isaac   if (isPlex) {
636da023fcSToby Isaac     *plex = dm;
646da023fcSToby Isaac     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
65f7148743SMatthew G. Knepley   } else {
66f7148743SMatthew G. Knepley     ierr = PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex);CHKERRQ(ierr);
67f7148743SMatthew G. Knepley     if (!*plex) {
686da023fcSToby Isaac       ierr = DMConvert(dm,DMPLEX,plex);CHKERRQ(ierr);
69f7148743SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex);CHKERRQ(ierr);
706da023fcSToby Isaac       if (copy) {
716da023fcSToby Isaac         PetscInt    i;
726da023fcSToby Isaac         PetscObject obj;
736da023fcSToby Isaac         const char *comps[3] = {"A","dmAux","dmCh"};
746da023fcSToby Isaac 
756da023fcSToby Isaac         ierr = DMCopyDMSNES(dm, *plex);CHKERRQ(ierr);
766da023fcSToby Isaac         for (i = 0; i < 3; i++) {
776da023fcSToby Isaac           ierr = PetscObjectQuery((PetscObject) dm, comps[i], &obj);CHKERRQ(ierr);
786da023fcSToby Isaac           ierr = PetscObjectCompose((PetscObject) *plex, comps[i], obj);CHKERRQ(ierr);
796da023fcSToby Isaac         }
806da023fcSToby Isaac       }
81f7148743SMatthew G. Knepley     } else {
82f7148743SMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) *plex);CHKERRQ(ierr);
83f7148743SMatthew G. Knepley     }
846da023fcSToby Isaac   }
856da023fcSToby Isaac   PetscFunctionReturn(0);
866da023fcSToby Isaac }
876da023fcSToby Isaac 
880adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx)
890adebc6cSBarry Smith {
90552f7358SJed Brown   PetscErrorCode ierr;
91552f7358SJed Brown 
92552f7358SJed Brown   PetscFunctionBegin;
93552f7358SJed Brown   PetscValidPointer(ctx, 2);
9495dccacaSBarry Smith   ierr = PetscNew(ctx);CHKERRQ(ierr);
951aa26658SKarl Rupp 
96552f7358SJed Brown   (*ctx)->comm   = comm;
97552f7358SJed Brown   (*ctx)->dim    = -1;
98552f7358SJed Brown   (*ctx)->nInput = 0;
990298fd71SBarry Smith   (*ctx)->points = NULL;
1000298fd71SBarry Smith   (*ctx)->cells  = NULL;
101552f7358SJed Brown   (*ctx)->n      = -1;
1020298fd71SBarry Smith   (*ctx)->coords = NULL;
103552f7358SJed Brown   PetscFunctionReturn(0);
104552f7358SJed Brown }
105552f7358SJed Brown 
1060adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim)
1070adebc6cSBarry Smith {
108552f7358SJed Brown   PetscFunctionBegin;
1090adebc6cSBarry Smith   if ((dim < 1) || (dim > 3)) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %d", dim);
110552f7358SJed Brown   ctx->dim = dim;
111552f7358SJed Brown   PetscFunctionReturn(0);
112552f7358SJed Brown }
113552f7358SJed Brown 
1140adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim)
1150adebc6cSBarry Smith {
116552f7358SJed Brown   PetscFunctionBegin;
117552f7358SJed Brown   PetscValidIntPointer(dim, 2);
118552f7358SJed Brown   *dim = ctx->dim;
119552f7358SJed Brown   PetscFunctionReturn(0);
120552f7358SJed Brown }
121552f7358SJed Brown 
1220adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof)
1230adebc6cSBarry Smith {
124552f7358SJed Brown   PetscFunctionBegin;
1250adebc6cSBarry Smith   if (dof < 1) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %d", dof);
126552f7358SJed Brown   ctx->dof = dof;
127552f7358SJed Brown   PetscFunctionReturn(0);
128552f7358SJed Brown }
129552f7358SJed Brown 
1300adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof)
1310adebc6cSBarry Smith {
132552f7358SJed Brown   PetscFunctionBegin;
133552f7358SJed Brown   PetscValidIntPointer(dof, 2);
134552f7358SJed Brown   *dof = ctx->dof;
135552f7358SJed Brown   PetscFunctionReturn(0);
136552f7358SJed Brown }
137552f7358SJed Brown 
1380adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[])
1390adebc6cSBarry Smith {
140552f7358SJed Brown   PetscErrorCode ierr;
141552f7358SJed Brown 
142552f7358SJed Brown   PetscFunctionBegin;
1430adebc6cSBarry Smith   if (ctx->dim < 0) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
1440adebc6cSBarry Smith   if (ctx->points)  SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet");
145552f7358SJed Brown   ctx->nInput = n;
1461aa26658SKarl Rupp 
147785e854fSJed Brown   ierr = PetscMalloc1(n*ctx->dim, &ctx->points);CHKERRQ(ierr);
148552f7358SJed Brown   ierr = PetscMemcpy(ctx->points, points, n*ctx->dim * sizeof(PetscReal));CHKERRQ(ierr);
149552f7358SJed Brown   PetscFunctionReturn(0);
150552f7358SJed Brown }
151552f7358SJed Brown 
1520adebc6cSBarry Smith PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints)
1530adebc6cSBarry Smith {
154552f7358SJed Brown   MPI_Comm          comm = ctx->comm;
155552f7358SJed Brown   PetscScalar       *a;
156552f7358SJed Brown   PetscInt          p, q, i;
157552f7358SJed Brown   PetscMPIInt       rank, size;
158552f7358SJed Brown   PetscErrorCode    ierr;
159552f7358SJed Brown   Vec               pointVec;
1603a93e3b7SToby Isaac   PetscSF           cellSF;
161552f7358SJed Brown   PetscLayout       layout;
162552f7358SJed Brown   PetscReal         *globalPoints;
163cb313848SJed Brown   PetscScalar       *globalPointsScalar;
164552f7358SJed Brown   const PetscInt    *ranges;
165552f7358SJed Brown   PetscMPIInt       *counts, *displs;
1663a93e3b7SToby Isaac   const PetscSFNode *foundCells;
1673a93e3b7SToby Isaac   const PetscInt    *foundPoints;
168552f7358SJed Brown   PetscMPIInt       *foundProcs, *globalProcs;
1693a93e3b7SToby Isaac   PetscInt          n, N, numFound;
170552f7358SJed Brown 
17119436ca2SJed Brown   PetscFunctionBegin;
17219436ca2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17319436ca2SJed Brown   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
17419436ca2SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1750adebc6cSBarry Smith   if (ctx->dim < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
17619436ca2SJed Brown   /* Locate points */
17719436ca2SJed Brown   n = ctx->nInput;
178552f7358SJed Brown   if (!redundantPoints) {
179552f7358SJed Brown     ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
180552f7358SJed Brown     ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
181552f7358SJed Brown     ierr = PetscLayoutSetLocalSize(layout, n);CHKERRQ(ierr);
182552f7358SJed Brown     ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
183552f7358SJed Brown     ierr = PetscLayoutGetSize(layout, &N);CHKERRQ(ierr);
184552f7358SJed Brown     /* Communicate all points to all processes */
185dcca6d9dSJed Brown     ierr = PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs);CHKERRQ(ierr);
186552f7358SJed Brown     ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
187552f7358SJed Brown     for (p = 0; p < size; ++p) {
188552f7358SJed Brown       counts[p] = (ranges[p+1] - ranges[p])*ctx->dim;
189552f7358SJed Brown       displs[p] = ranges[p]*ctx->dim;
190552f7358SJed Brown     }
191552f7358SJed Brown     ierr = MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm);CHKERRQ(ierr);
192552f7358SJed Brown   } else {
193552f7358SJed Brown     N = n;
194552f7358SJed Brown     globalPoints = ctx->points;
19538ea73c8SJed Brown     counts = displs = NULL;
19638ea73c8SJed Brown     layout = NULL;
197552f7358SJed Brown   }
198552f7358SJed Brown #if 0
199dcca6d9dSJed Brown   ierr = PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
20019436ca2SJed Brown   /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */
201552f7358SJed Brown #else
202cb313848SJed Brown #if defined(PETSC_USE_COMPLEX)
20346b3086cSToby Isaac   ierr = PetscMalloc1(N*ctx->dim,&globalPointsScalar);CHKERRQ(ierr);
20446b3086cSToby Isaac   for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i];
205cb313848SJed Brown #else
206cb313848SJed Brown   globalPointsScalar = globalPoints;
207cb313848SJed Brown #endif
20804706141SMatthew G Knepley   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec);CHKERRQ(ierr);
209dcca6d9dSJed Brown   ierr = PetscMalloc2(N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
2107b5f2079SMatthew G. Knepley   for (p = 0; p < N; ++p) {foundProcs[p] = size;}
2113a93e3b7SToby Isaac   cellSF = NULL;
2122d1fa6caSMatthew G. Knepley   ierr = DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF);CHKERRQ(ierr);
2133a93e3b7SToby Isaac   ierr = PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells);CHKERRQ(ierr);
214552f7358SJed Brown #endif
2153a93e3b7SToby Isaac   for (p = 0; p < numFound; ++p) {
2163a93e3b7SToby Isaac     if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank;
217552f7358SJed Brown   }
218552f7358SJed Brown   /* Let the lowest rank process own each point */
219b2566f29SBarry Smith   ierr   = MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm);CHKERRQ(ierr);
220552f7358SJed Brown   ctx->n = 0;
221552f7358SJed Brown   for (p = 0; p < N; ++p) {
222e5b268a4SToby Isaac     if (globalProcs[p] == size) SETERRQ4(comm, PETSC_ERR_PLIB, "Point %d: %g %g %g not located in mesh", p, (double)globalPoints[p*ctx->dim+0], (double)(ctx->dim > 1 ? globalPoints[p*ctx->dim+1] : 0.0), (double)(ctx->dim > 2 ? globalPoints[p*ctx->dim+2] : 0.0));
2231aa26658SKarl Rupp     else if (globalProcs[p] == rank) ctx->n++;
224552f7358SJed Brown   }
225552f7358SJed Brown   /* Create coordinates vector and array of owned cells */
226785e854fSJed Brown   ierr = PetscMalloc1(ctx->n, &ctx->cells);CHKERRQ(ierr);
227552f7358SJed Brown   ierr = VecCreate(comm, &ctx->coords);CHKERRQ(ierr);
228552f7358SJed Brown   ierr = VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE);CHKERRQ(ierr);
229552f7358SJed Brown   ierr = VecSetBlockSize(ctx->coords, ctx->dim);CHKERRQ(ierr);
230c0dedaeaSBarry Smith   ierr = VecSetType(ctx->coords,VECSTANDARD);CHKERRQ(ierr);
231552f7358SJed Brown   ierr = VecGetArray(ctx->coords, &a);CHKERRQ(ierr);
232552f7358SJed Brown   for (p = 0, q = 0, i = 0; p < N; ++p) {
233552f7358SJed Brown     if (globalProcs[p] == rank) {
234552f7358SJed Brown       PetscInt d;
235552f7358SJed Brown 
2361aa26658SKarl Rupp       for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d];
237f317b747SMatthew G. Knepley       ctx->cells[q] = foundCells[q].index;
238f317b747SMatthew G. Knepley       ++q;
239552f7358SJed Brown     }
240552f7358SJed Brown   }
241552f7358SJed Brown   ierr = VecRestoreArray(ctx->coords, &a);CHKERRQ(ierr);
242552f7358SJed Brown #if 0
243552f7358SJed Brown   ierr = PetscFree3(foundCells,foundProcs,globalProcs);CHKERRQ(ierr);
244552f7358SJed Brown #else
245552f7358SJed Brown   ierr = PetscFree2(foundProcs,globalProcs);CHKERRQ(ierr);
2463a93e3b7SToby Isaac   ierr = PetscSFDestroy(&cellSF);CHKERRQ(ierr);
247552f7358SJed Brown   ierr = VecDestroy(&pointVec);CHKERRQ(ierr);
248552f7358SJed Brown #endif
249cb313848SJed Brown   if ((void*)globalPointsScalar != (void*)globalPoints) {ierr = PetscFree(globalPointsScalar);CHKERRQ(ierr);}
250d343d804SMatthew G. Knepley   if (!redundantPoints) {ierr = PetscFree3(globalPoints,counts,displs);CHKERRQ(ierr);}
251552f7358SJed Brown   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
252552f7358SJed Brown   PetscFunctionReturn(0);
253552f7358SJed Brown }
254552f7358SJed Brown 
2550adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates)
2560adebc6cSBarry Smith {
257552f7358SJed Brown   PetscFunctionBegin;
258552f7358SJed Brown   PetscValidPointer(coordinates, 2);
2590adebc6cSBarry Smith   if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
260552f7358SJed Brown   *coordinates = ctx->coords;
261552f7358SJed Brown   PetscFunctionReturn(0);
262552f7358SJed Brown }
263552f7358SJed Brown 
2640adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v)
2650adebc6cSBarry Smith {
266552f7358SJed Brown   PetscErrorCode ierr;
267552f7358SJed Brown 
268552f7358SJed Brown   PetscFunctionBegin;
269552f7358SJed Brown   PetscValidPointer(v, 2);
2700adebc6cSBarry Smith   if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
271552f7358SJed Brown   ierr = VecCreate(ctx->comm, v);CHKERRQ(ierr);
272552f7358SJed Brown   ierr = VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE);CHKERRQ(ierr);
273552f7358SJed Brown   ierr = VecSetBlockSize(*v, ctx->dof);CHKERRQ(ierr);
274c0dedaeaSBarry Smith   ierr = VecSetType(*v,VECSTANDARD);CHKERRQ(ierr);
275552f7358SJed Brown   PetscFunctionReturn(0);
276552f7358SJed Brown }
277552f7358SJed Brown 
2780adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v)
2790adebc6cSBarry Smith {
280552f7358SJed Brown   PetscErrorCode ierr;
281552f7358SJed Brown 
282552f7358SJed Brown   PetscFunctionBegin;
283552f7358SJed Brown   PetscValidPointer(v, 2);
2840adebc6cSBarry Smith   if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
285552f7358SJed Brown   ierr = VecDestroy(v);CHKERRQ(ierr);
286552f7358SJed Brown   PetscFunctionReturn(0);
287552f7358SJed Brown }
288552f7358SJed Brown 
2897a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
290a6dfd86eSKarl Rupp {
291552f7358SJed Brown   PetscReal      *v0, *J, *invJ, detJ;
29256044e6dSMatthew G. Knepley   const PetscScalar *coords;
29356044e6dSMatthew G. Knepley   PetscScalar    *a;
294552f7358SJed Brown   PetscInt       p;
295552f7358SJed Brown   PetscErrorCode ierr;
296552f7358SJed Brown 
297552f7358SJed Brown   PetscFunctionBegin;
298dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
29956044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
300552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
301552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
302552f7358SJed Brown     PetscInt     c = ctx->cells[p];
303a1e44745SMatthew G. Knepley     PetscScalar *x = NULL;
304552f7358SJed Brown     PetscReal    xi[4];
305552f7358SJed Brown     PetscInt     d, f, comp;
306552f7358SJed Brown 
3078e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
308e5b268a4SToby Isaac     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", (double)detJ, c);
3090298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
3101aa26658SKarl Rupp     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
3111aa26658SKarl Rupp 
312552f7358SJed Brown     for (d = 0; d < ctx->dim; ++d) {
313552f7358SJed Brown       xi[d] = 0.0;
3141aa26658SKarl Rupp       for (f = 0; f < ctx->dim; ++f) xi[d] += invJ[d*ctx->dim+f]*0.5*PetscRealPart(coords[p*ctx->dim+f] - v0[f]);
3151aa26658SKarl Rupp       for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] += PetscRealPart(x[(d+1)*ctx->dof+comp] - x[0*ctx->dof+comp])*xi[d];
316552f7358SJed Brown     }
3170298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
318552f7358SJed Brown   }
319552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
32056044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
321552f7358SJed Brown   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
322552f7358SJed Brown   PetscFunctionReturn(0);
323552f7358SJed Brown }
324552f7358SJed Brown 
3257a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
3267a1931ceSMatthew G. Knepley {
3277a1931ceSMatthew G. Knepley   PetscReal      *v0, *J, *invJ, detJ;
32856044e6dSMatthew G. Knepley   const PetscScalar *coords;
32956044e6dSMatthew G. Knepley   PetscScalar    *a;
3307a1931ceSMatthew G. Knepley   PetscInt       p;
3317a1931ceSMatthew G. Knepley   PetscErrorCode ierr;
3327a1931ceSMatthew G. Knepley 
3337a1931ceSMatthew G. Knepley   PetscFunctionBegin;
334dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
33556044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
3367a1931ceSMatthew G. Knepley   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
3377a1931ceSMatthew G. Knepley   for (p = 0; p < ctx->n; ++p) {
3387a1931ceSMatthew G. Knepley     PetscInt       c = ctx->cells[p];
3397a1931ceSMatthew G. Knepley     const PetscInt order[3] = {2, 1, 3};
3402584bbe8SMatthew G. Knepley     PetscScalar   *x = NULL;
3417a1931ceSMatthew G. Knepley     PetscReal      xi[4];
3427a1931ceSMatthew G. Knepley     PetscInt       d, f, comp;
3437a1931ceSMatthew G. Knepley 
3448e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
345e5b268a4SToby Isaac     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", (double)detJ, c);
3467a1931ceSMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
3477a1931ceSMatthew G. Knepley     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
3487a1931ceSMatthew G. Knepley 
3497a1931ceSMatthew G. Knepley     for (d = 0; d < ctx->dim; ++d) {
3507a1931ceSMatthew G. Knepley       xi[d] = 0.0;
3517a1931ceSMatthew G. Knepley       for (f = 0; f < ctx->dim; ++f) xi[d] += invJ[d*ctx->dim+f]*0.5*PetscRealPart(coords[p*ctx->dim+f] - v0[f]);
3527a1931ceSMatthew G. Knepley       for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] += PetscRealPart(x[order[d]*ctx->dof+comp] - x[0*ctx->dof+comp])*xi[d];
3537a1931ceSMatthew G. Knepley     }
3547a1931ceSMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
3557a1931ceSMatthew G. Knepley   }
3567a1931ceSMatthew G. Knepley   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
35756044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
3587a1931ceSMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
3597a1931ceSMatthew G. Knepley   PetscFunctionReturn(0);
3607a1931ceSMatthew G. Knepley }
3617a1931ceSMatthew G. Knepley 
3625820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
363552f7358SJed Brown {
364552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
365552f7358SJed Brown   const PetscScalar x0        = vertices[0];
366552f7358SJed Brown   const PetscScalar y0        = vertices[1];
367552f7358SJed Brown   const PetscScalar x1        = vertices[2];
368552f7358SJed Brown   const PetscScalar y1        = vertices[3];
369552f7358SJed Brown   const PetscScalar x2        = vertices[4];
370552f7358SJed Brown   const PetscScalar y2        = vertices[5];
371552f7358SJed Brown   const PetscScalar x3        = vertices[6];
372552f7358SJed Brown   const PetscScalar y3        = vertices[7];
373552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
374552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
375552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
376552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
377552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
378552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
37956044e6dSMatthew G. Knepley   const PetscScalar *ref;
38056044e6dSMatthew G. Knepley   PetscScalar       *real;
381552f7358SJed Brown   PetscErrorCode    ierr;
382552f7358SJed Brown 
383552f7358SJed Brown   PetscFunctionBegin;
38456044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
385552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
386552f7358SJed Brown   {
387552f7358SJed Brown     const PetscScalar p0 = ref[0];
388552f7358SJed Brown     const PetscScalar p1 = ref[1];
389552f7358SJed Brown 
390552f7358SJed Brown     real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1;
391552f7358SJed Brown     real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1;
392552f7358SJed Brown   }
393552f7358SJed Brown   ierr = PetscLogFlops(28);CHKERRQ(ierr);
39456044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
395552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
396552f7358SJed Brown   PetscFunctionReturn(0);
397552f7358SJed Brown }
398552f7358SJed Brown 
399af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
400d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
401552f7358SJed Brown {
402552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
403552f7358SJed Brown   const PetscScalar x0        = vertices[0];
404552f7358SJed Brown   const PetscScalar y0        = vertices[1];
405552f7358SJed Brown   const PetscScalar x1        = vertices[2];
406552f7358SJed Brown   const PetscScalar y1        = vertices[3];
407552f7358SJed Brown   const PetscScalar x2        = vertices[4];
408552f7358SJed Brown   const PetscScalar y2        = vertices[5];
409552f7358SJed Brown   const PetscScalar x3        = vertices[6];
410552f7358SJed Brown   const PetscScalar y3        = vertices[7];
411552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
412552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
41356044e6dSMatthew G. Knepley   const PetscScalar *ref;
414552f7358SJed Brown   PetscErrorCode    ierr;
415552f7358SJed Brown 
416552f7358SJed Brown   PetscFunctionBegin;
41756044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
418552f7358SJed Brown   {
419552f7358SJed Brown     const PetscScalar x       = ref[0];
420552f7358SJed Brown     const PetscScalar y       = ref[1];
421552f7358SJed Brown     const PetscInt    rows[2] = {0, 1};
422da80777bSKarl Rupp     PetscScalar       values[4];
423da80777bSKarl Rupp 
424da80777bSKarl Rupp     values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5;
425da80777bSKarl Rupp     values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5;
42694ab13aaSBarry Smith     ierr      = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr);
427552f7358SJed Brown   }
428552f7358SJed Brown   ierr = PetscLogFlops(30);CHKERRQ(ierr);
42956044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
43094ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
43194ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
432552f7358SJed Brown   PetscFunctionReturn(0);
433552f7358SJed Brown }
434552f7358SJed Brown 
435a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
436a6dfd86eSKarl Rupp {
437fafc0619SMatthew G Knepley   DM             dmCoord;
438de73a395SMatthew G. Knepley   PetscFE        fem = NULL;
439552f7358SJed Brown   SNES           snes;
440552f7358SJed Brown   KSP            ksp;
441552f7358SJed Brown   PC             pc;
442552f7358SJed Brown   Vec            coordsLocal, r, ref, real;
443552f7358SJed Brown   Mat            J;
44456044e6dSMatthew G. Knepley   const PetscScalar *coords;
44556044e6dSMatthew G. Knepley   PetscScalar    *a;
446de73a395SMatthew G. Knepley   PetscInt       Nf, p;
4475509d985SMatthew G. Knepley   const PetscInt dof = ctx->dof;
448552f7358SJed Brown   PetscErrorCode ierr;
449552f7358SJed Brown 
450552f7358SJed Brown   PetscFunctionBegin;
451de73a395SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
452de73a395SMatthew G. Knepley   if (Nf) {ierr = DMGetField(dm, 0, (PetscObject *) &fem);CHKERRQ(ierr);}
453552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
454fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
455552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
456552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr);
457552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
458552f7358SJed Brown   ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr);
459c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
460552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
461552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
462552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
463552f7358SJed Brown   ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr);
464552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
465552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
4660298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr);
4670298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr);
468552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
469552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
470552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
471552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
472552f7358SJed Brown 
47356044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
474552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
475552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
476a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
477552f7358SJed Brown     PetscScalar *xi;
478cb313848SJed Brown     PetscReal    xir[2];
479552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
480552f7358SJed Brown 
481552f7358SJed Brown     /* Can make this do all points at once */
4820298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
4830adebc6cSBarry Smith     if (4*2 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %d should be %d", coordSize, 4*2);
4840298fd71SBarry Smith     ierr   = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
4850298fd71SBarry Smith     ierr   = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
4860298fd71SBarry Smith     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
487552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
488552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
489552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
490552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
491552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
492552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
493cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
494cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
4955509d985SMatthew G. Knepley     if (4*dof != xSize) {
4965509d985SMatthew G. Knepley       PetscReal *B;
4975509d985SMatthew G. Knepley       PetscInt   d;
4981aa26658SKarl Rupp 
4995509d985SMatthew G. Knepley       xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0;
5005509d985SMatthew G. Knepley       ierr = PetscFEGetTabulation(fem, 1, xir, &B, NULL, NULL);CHKERRQ(ierr);
5015509d985SMatthew G. Knepley       for (comp = 0; comp < dof; ++comp) {
5025509d985SMatthew G. Knepley         a[p*dof+comp] = 0.0;
5035509d985SMatthew G. Knepley         for (d = 0; d < xSize/dof; ++d) {
5045509d985SMatthew G. Knepley           a[p*dof+comp] += x[d*dof+comp]*B[d*dof+comp];
5055509d985SMatthew G. Knepley         }
5065509d985SMatthew G. Knepley       }
5075509d985SMatthew G. Knepley       ierr = PetscFERestoreTabulation(fem, 1, xir, &B, NULL, NULL);CHKERRQ(ierr);
5085509d985SMatthew G. Knepley     } else {
5095509d985SMatthew G. Knepley       for (comp = 0; comp < dof; ++comp)
5105509d985SMatthew G. Knepley         a[p*dof+comp] = x[0*dof+comp]*(1 - xir[0])*(1 - xir[1]) + x[1*dof+comp]*xir[0]*(1 - xir[1]) + x[2*dof+comp]*xir[0]*xir[1] + x[3*dof+comp]*(1 - xir[0])*xir[1];
5115509d985SMatthew G. Knepley     }
512552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
5130298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
5140298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
515552f7358SJed Brown   }
516552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
51756044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
518552f7358SJed Brown 
519552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
520552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
521552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
522552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
523552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
524552f7358SJed Brown   PetscFunctionReturn(0);
525552f7358SJed Brown }
526552f7358SJed Brown 
5275820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
528552f7358SJed Brown {
529552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
530552f7358SJed Brown   const PetscScalar x0        = vertices[0];
531552f7358SJed Brown   const PetscScalar y0        = vertices[1];
532552f7358SJed Brown   const PetscScalar z0        = vertices[2];
5337a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
5347a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
5357a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
536552f7358SJed Brown   const PetscScalar x2        = vertices[6];
537552f7358SJed Brown   const PetscScalar y2        = vertices[7];
538552f7358SJed Brown   const PetscScalar z2        = vertices[8];
5397a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
5407a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
5417a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
542552f7358SJed Brown   const PetscScalar x4        = vertices[12];
543552f7358SJed Brown   const PetscScalar y4        = vertices[13];
544552f7358SJed Brown   const PetscScalar z4        = vertices[14];
545552f7358SJed Brown   const PetscScalar x5        = vertices[15];
546552f7358SJed Brown   const PetscScalar y5        = vertices[16];
547552f7358SJed Brown   const PetscScalar z5        = vertices[17];
548552f7358SJed Brown   const PetscScalar x6        = vertices[18];
549552f7358SJed Brown   const PetscScalar y6        = vertices[19];
550552f7358SJed Brown   const PetscScalar z6        = vertices[20];
551552f7358SJed Brown   const PetscScalar x7        = vertices[21];
552552f7358SJed Brown   const PetscScalar y7        = vertices[22];
553552f7358SJed Brown   const PetscScalar z7        = vertices[23];
554552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
555552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
556552f7358SJed Brown   const PetscScalar h_1       = z1 - z0;
557552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
558552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
559552f7358SJed Brown   const PetscScalar h_3       = z3 - z0;
560552f7358SJed Brown   const PetscScalar f_4       = x4 - x0;
561552f7358SJed Brown   const PetscScalar g_4       = y4 - y0;
562552f7358SJed Brown   const PetscScalar h_4       = z4 - z0;
563552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
564552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
565552f7358SJed Brown   const PetscScalar h_01      = z2 - z1 - z3 + z0;
566552f7358SJed Brown   const PetscScalar f_12      = x7 - x3 - x4 + x0;
567552f7358SJed Brown   const PetscScalar g_12      = y7 - y3 - y4 + y0;
568552f7358SJed Brown   const PetscScalar h_12      = z7 - z3 - z4 + z0;
569552f7358SJed Brown   const PetscScalar f_02      = x5 - x1 - x4 + x0;
570552f7358SJed Brown   const PetscScalar g_02      = y5 - y1 - y4 + y0;
571552f7358SJed Brown   const PetscScalar h_02      = z5 - z1 - z4 + z0;
572552f7358SJed Brown   const PetscScalar f_012     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
573552f7358SJed Brown   const PetscScalar g_012     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
574552f7358SJed Brown   const PetscScalar h_012     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
57556044e6dSMatthew G. Knepley   const PetscScalar *ref;
57656044e6dSMatthew G. Knepley   PetscScalar       *real;
577552f7358SJed Brown   PetscErrorCode    ierr;
578552f7358SJed Brown 
579552f7358SJed Brown   PetscFunctionBegin;
58056044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
581552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
582552f7358SJed Brown   {
583552f7358SJed Brown     const PetscScalar p0 = ref[0];
584552f7358SJed Brown     const PetscScalar p1 = ref[1];
585552f7358SJed Brown     const PetscScalar p2 = ref[2];
586552f7358SJed Brown 
587552f7358SJed Brown     real[0] = x0 + f_1*p0 + f_3*p1 + f_4*p2 + f_01*p0*p1 + f_12*p1*p2 + f_02*p0*p2 + f_012*p0*p1*p2;
588552f7358SJed Brown     real[1] = y0 + g_1*p0 + g_3*p1 + g_4*p2 + g_01*p0*p1 + g_01*p0*p1 + g_12*p1*p2 + g_02*p0*p2 + g_012*p0*p1*p2;
589552f7358SJed Brown     real[2] = z0 + h_1*p0 + h_3*p1 + h_4*p2 + h_01*p0*p1 + h_01*p0*p1 + h_12*p1*p2 + h_02*p0*p2 + h_012*p0*p1*p2;
590552f7358SJed Brown   }
591552f7358SJed Brown   ierr = PetscLogFlops(114);CHKERRQ(ierr);
59256044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
593552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
594552f7358SJed Brown   PetscFunctionReturn(0);
595552f7358SJed Brown }
596552f7358SJed Brown 
597d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
598552f7358SJed Brown {
599552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
600552f7358SJed Brown   const PetscScalar x0        = vertices[0];
601552f7358SJed Brown   const PetscScalar y0        = vertices[1];
602552f7358SJed Brown   const PetscScalar z0        = vertices[2];
6037a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
6047a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
6057a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
606552f7358SJed Brown   const PetscScalar x2        = vertices[6];
607552f7358SJed Brown   const PetscScalar y2        = vertices[7];
608552f7358SJed Brown   const PetscScalar z2        = vertices[8];
6097a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
6107a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
6117a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
612552f7358SJed Brown   const PetscScalar x4        = vertices[12];
613552f7358SJed Brown   const PetscScalar y4        = vertices[13];
614552f7358SJed Brown   const PetscScalar z4        = vertices[14];
615552f7358SJed Brown   const PetscScalar x5        = vertices[15];
616552f7358SJed Brown   const PetscScalar y5        = vertices[16];
617552f7358SJed Brown   const PetscScalar z5        = vertices[17];
618552f7358SJed Brown   const PetscScalar x6        = vertices[18];
619552f7358SJed Brown   const PetscScalar y6        = vertices[19];
620552f7358SJed Brown   const PetscScalar z6        = vertices[20];
621552f7358SJed Brown   const PetscScalar x7        = vertices[21];
622552f7358SJed Brown   const PetscScalar y7        = vertices[22];
623552f7358SJed Brown   const PetscScalar z7        = vertices[23];
624552f7358SJed Brown   const PetscScalar f_xy      = x2 - x1 - x3 + x0;
625552f7358SJed Brown   const PetscScalar g_xy      = y2 - y1 - y3 + y0;
626552f7358SJed Brown   const PetscScalar h_xy      = z2 - z1 - z3 + z0;
627552f7358SJed Brown   const PetscScalar f_yz      = x7 - x3 - x4 + x0;
628552f7358SJed Brown   const PetscScalar g_yz      = y7 - y3 - y4 + y0;
629552f7358SJed Brown   const PetscScalar h_yz      = z7 - z3 - z4 + z0;
630552f7358SJed Brown   const PetscScalar f_xz      = x5 - x1 - x4 + x0;
631552f7358SJed Brown   const PetscScalar g_xz      = y5 - y1 - y4 + y0;
632552f7358SJed Brown   const PetscScalar h_xz      = z5 - z1 - z4 + z0;
633552f7358SJed Brown   const PetscScalar f_xyz     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
634552f7358SJed Brown   const PetscScalar g_xyz     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
635552f7358SJed Brown   const PetscScalar h_xyz     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
63656044e6dSMatthew G. Knepley   const PetscScalar *ref;
637552f7358SJed Brown   PetscErrorCode    ierr;
638552f7358SJed Brown 
639552f7358SJed Brown   PetscFunctionBegin;
64056044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
641552f7358SJed Brown   {
642552f7358SJed Brown     const PetscScalar x       = ref[0];
643552f7358SJed Brown     const PetscScalar y       = ref[1];
644552f7358SJed Brown     const PetscScalar z       = ref[2];
645552f7358SJed Brown     const PetscInt    rows[3] = {0, 1, 2};
646da80777bSKarl Rupp     PetscScalar       values[9];
647da80777bSKarl Rupp 
648da80777bSKarl Rupp     values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0;
649da80777bSKarl Rupp     values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0;
650da80777bSKarl Rupp     values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0;
651da80777bSKarl Rupp     values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0;
652da80777bSKarl Rupp     values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0;
653da80777bSKarl Rupp     values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0;
654da80777bSKarl Rupp     values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0;
655da80777bSKarl Rupp     values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0;
656da80777bSKarl Rupp     values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0;
6571aa26658SKarl Rupp 
65894ab13aaSBarry Smith     ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr);
659552f7358SJed Brown   }
660552f7358SJed Brown   ierr = PetscLogFlops(152);CHKERRQ(ierr);
66156044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
66294ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66394ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
664552f7358SJed Brown   PetscFunctionReturn(0);
665552f7358SJed Brown }
666552f7358SJed Brown 
667a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
668a6dfd86eSKarl Rupp {
669fafc0619SMatthew G Knepley   DM             dmCoord;
670552f7358SJed Brown   SNES           snes;
671552f7358SJed Brown   KSP            ksp;
672552f7358SJed Brown   PC             pc;
673552f7358SJed Brown   Vec            coordsLocal, r, ref, real;
674552f7358SJed Brown   Mat            J;
67556044e6dSMatthew G. Knepley   const PetscScalar *coords;
67656044e6dSMatthew G. Knepley   PetscScalar    *a;
677552f7358SJed Brown   PetscInt       p;
678552f7358SJed Brown   PetscErrorCode ierr;
679552f7358SJed Brown 
680552f7358SJed Brown   PetscFunctionBegin;
681552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
682fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
683552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
684552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr);
685552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
686552f7358SJed Brown   ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr);
687c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
688552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
689552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
690552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
691552f7358SJed Brown   ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr);
692552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
693552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
6940298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr);
6950298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr);
696552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
697552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
698552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
699552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
700552f7358SJed Brown 
70156044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
702552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
703552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
704a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
705552f7358SJed Brown     PetscScalar *xi;
706cb313848SJed Brown     PetscReal    xir[3];
707552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
708552f7358SJed Brown 
709552f7358SJed Brown     /* Can make this do all points at once */
7100298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
7110adebc6cSBarry Smith     if (8*3 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %d should be %d", coordSize, 8*3);
7120298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
7130adebc6cSBarry Smith     if (8*ctx->dof != xSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %d should be %d", xSize, 8*ctx->dof);
7140298fd71SBarry Smith     ierr   = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
7150298fd71SBarry Smith     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
716552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
717552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
718552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
719552f7358SJed Brown     xi[2]  = coords[p*ctx->dim+2];
720552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
721552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
722552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
723cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
724cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
725cb313848SJed Brown     xir[2] = PetscRealPart(xi[2]);
726552f7358SJed Brown     for (comp = 0; comp < ctx->dof; ++comp) {
727552f7358SJed Brown       a[p*ctx->dof+comp] =
728cb313848SJed Brown         x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) +
7297a1931ceSMatthew G. Knepley         x[3*ctx->dof+comp]*    xir[0]*(1-xir[1])*(1-xir[2]) +
730cb313848SJed Brown         x[2*ctx->dof+comp]*    xir[0]*    xir[1]*(1-xir[2]) +
7317a1931ceSMatthew G. Knepley         x[1*ctx->dof+comp]*(1-xir[0])*    xir[1]*(1-xir[2]) +
732cb313848SJed Brown         x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*   xir[2] +
733cb313848SJed Brown         x[5*ctx->dof+comp]*    xir[0]*(1-xir[1])*   xir[2] +
734cb313848SJed Brown         x[6*ctx->dof+comp]*    xir[0]*    xir[1]*   xir[2] +
735cb313848SJed Brown         x[7*ctx->dof+comp]*(1-xir[0])*    xir[1]*   xir[2];
736552f7358SJed Brown     }
737552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
7380298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
7390298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
740552f7358SJed Brown   }
741552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
74256044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
743552f7358SJed Brown 
744552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
745552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
746552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
747552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
748552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
749552f7358SJed Brown   PetscFunctionReturn(0);
750552f7358SJed Brown }
751552f7358SJed Brown 
752552f7358SJed Brown /*
753552f7358SJed Brown   Input Parameters:
754552f7358SJed Brown + ctx - The DMInterpolationInfo context
755552f7358SJed Brown . dm  - The DM
756552f7358SJed Brown - x   - The local vector containing the field to be interpolated
757552f7358SJed Brown 
758552f7358SJed Brown   Output Parameters:
759552f7358SJed Brown . v   - The vector containing the interpolated values
760552f7358SJed Brown */
7610adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v)
7620adebc6cSBarry Smith {
763552f7358SJed Brown   PetscInt       dim, coneSize, n;
764552f7358SJed Brown   PetscErrorCode ierr;
765552f7358SJed Brown 
766552f7358SJed Brown   PetscFunctionBegin;
767552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
768552f7358SJed Brown   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
769552f7358SJed Brown   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
770552f7358SJed Brown   ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
7710adebc6cSBarry Smith   if (n != ctx->n*ctx->dof) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %d should be %d", n, ctx->n*ctx->dof);
772552f7358SJed Brown   if (n) {
773c73cfb54SMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
774552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, ctx->cells[0], &coneSize);CHKERRQ(ierr);
775552f7358SJed Brown     if (dim == 2) {
776552f7358SJed Brown       if (coneSize == 3) {
7777a1931ceSMatthew G. Knepley         ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr);
778552f7358SJed Brown       } else if (coneSize == 4) {
779552f7358SJed Brown         ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr);
7800adebc6cSBarry Smith       } else SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dimension %d for point interpolation", dim);
781552f7358SJed Brown     } else if (dim == 3) {
782552f7358SJed Brown       if (coneSize == 4) {
7837a1931ceSMatthew G. Knepley         ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr);
784552f7358SJed Brown       } else {
785552f7358SJed Brown         ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr);
786552f7358SJed Brown       }
7870adebc6cSBarry Smith     } else SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dimension %d for point interpolation", dim);
788552f7358SJed Brown   }
789552f7358SJed Brown   PetscFunctionReturn(0);
790552f7358SJed Brown }
791552f7358SJed Brown 
7920adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx)
7930adebc6cSBarry Smith {
794552f7358SJed Brown   PetscErrorCode ierr;
795552f7358SJed Brown 
796552f7358SJed Brown   PetscFunctionBegin;
797552f7358SJed Brown   PetscValidPointer(ctx, 2);
798552f7358SJed Brown   ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr);
799552f7358SJed Brown   ierr = PetscFree((*ctx)->points);CHKERRQ(ierr);
800552f7358SJed Brown   ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr);
801552f7358SJed Brown   ierr = PetscFree(*ctx);CHKERRQ(ierr);
8020298fd71SBarry Smith   *ctx = NULL;
803552f7358SJed Brown   PetscFunctionReturn(0);
804552f7358SJed Brown }
805cc0c4584SMatthew G. Knepley 
806cc0c4584SMatthew G. Knepley /*@C
807cc0c4584SMatthew G. Knepley   SNESMonitorFields - Monitors the residual for each field separately
808cc0c4584SMatthew G. Knepley 
809cc0c4584SMatthew G. Knepley   Collective on SNES
810cc0c4584SMatthew G. Knepley 
811cc0c4584SMatthew G. Knepley   Input Parameters:
812cc0c4584SMatthew G. Knepley + snes   - the SNES context
813cc0c4584SMatthew G. Knepley . its    - iteration number
814cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual
815d43b4f6eSBarry Smith - vf  - PetscViewerAndFormat of type ASCII
816cc0c4584SMatthew G. Knepley 
817cc0c4584SMatthew G. Knepley   Notes:
818cc0c4584SMatthew G. Knepley   This routine prints the residual norm at each iteration.
819cc0c4584SMatthew G. Knepley 
820cc0c4584SMatthew G. Knepley   Level: intermediate
821cc0c4584SMatthew G. Knepley 
822cc0c4584SMatthew G. Knepley .keywords: SNES, nonlinear, default, monitor, norm
823cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault()
824cc0c4584SMatthew G. Knepley @*/
825d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
826cc0c4584SMatthew G. Knepley {
827d43b4f6eSBarry Smith   PetscViewer        viewer = vf->viewer;
828cc0c4584SMatthew G. Knepley   Vec                res;
829cc0c4584SMatthew G. Knepley   DM                 dm;
830cc0c4584SMatthew G. Knepley   PetscSection       s;
831cc0c4584SMatthew G. Knepley   const PetscScalar *r;
832cc0c4584SMatthew G. Knepley   PetscReal         *lnorms, *norms;
833cc0c4584SMatthew G. Knepley   PetscInt           numFields, f, pStart, pEnd, p;
834cc0c4584SMatthew G. Knepley   PetscErrorCode     ierr;
835cc0c4584SMatthew G. Knepley 
836cc0c4584SMatthew G. Knepley   PetscFunctionBegin;
8374d4332d5SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
838cc0c4584SMatthew G. Knepley   ierr = SNESGetFunction(snes, &res, 0, 0);CHKERRQ(ierr);
839cc0c4584SMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
840cc0c4584SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
841cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr);
842cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
843cc0c4584SMatthew G. Knepley   ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr);
844cc0c4584SMatthew G. Knepley   ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr);
845cc0c4584SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
846cc0c4584SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
847cc0c4584SMatthew G. Knepley       PetscInt fdof, foff, d;
848cc0c4584SMatthew G. Knepley 
849cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr);
850cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr);
851cc0c4584SMatthew G. Knepley       for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d]));
852cc0c4584SMatthew G. Knepley     }
853cc0c4584SMatthew G. Knepley   }
854cc0c4584SMatthew G. Knepley   ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr);
855b2566f29SBarry Smith   ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);
856d43b4f6eSBarry Smith   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
857cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
858cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr);
859cc0c4584SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
860cc0c4584SMatthew G. Knepley     if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
861cc0c4584SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr);
862cc0c4584SMatthew G. Knepley   }
863cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr);
864cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
865d43b4f6eSBarry Smith   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
866cc0c4584SMatthew G. Knepley   ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr);
867cc0c4584SMatthew G. Knepley   PetscFunctionReturn(0);
868cc0c4584SMatthew G. Knepley }
86924cdb843SMatthew G. Knepley 
87024cdb843SMatthew G. Knepley /********************* Residual Computation **************************/
87124cdb843SMatthew G. Knepley 
8724a3e9fdbSToby Isaac static PetscErrorCode PetscContainerUserDestroy_PetscFEGeom (void *ctx)
8737d4028c8SMatthew G. Knepley {
8744a3e9fdbSToby Isaac   PetscFEGeom *geom = (PetscFEGeom *) ctx;
8757d4028c8SMatthew G. Knepley   PetscErrorCode ierr;
8767d4028c8SMatthew G. Knepley 
8777d4028c8SMatthew G. Knepley   PetscFunctionBegin;
8784a3e9fdbSToby Isaac   ierr = PetscFEGeomDestroy(&geom);CHKERRQ(ierr);
8794a3e9fdbSToby Isaac   PetscFunctionReturn(0);
8807d4028c8SMatthew G. Knepley }
8814a3e9fdbSToby Isaac 
8824a3e9fdbSToby Isaac static PetscErrorCode DMSNESGetFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom)
8834a3e9fdbSToby Isaac {
8844a3e9fdbSToby Isaac   char            composeStr[33] = {0};
8854a3e9fdbSToby Isaac   PetscObjectId   id;
8864a3e9fdbSToby Isaac   PetscContainer  container;
8874a3e9fdbSToby Isaac   PetscErrorCode  ierr;
8884a3e9fdbSToby Isaac 
8894a3e9fdbSToby Isaac   PetscFunctionBegin;
8904a3e9fdbSToby Isaac   ierr = PetscObjectGetId((PetscObject)quad,&id);CHKERRQ(ierr);
8914a3e9fdbSToby Isaac   ierr = PetscSNPrintf(composeStr, 32, "DMSNESGetFEGeom_%x\n", id);CHKERRQ(ierr);
8924a3e9fdbSToby Isaac   ierr = PetscObjectQuery((PetscObject) pointIS, composeStr, (PetscObject *) &container);CHKERRQ(ierr);
8934a3e9fdbSToby Isaac   if (container) {
8944a3e9fdbSToby Isaac     ierr = PetscContainerGetPointer(container, (void **) geom);CHKERRQ(ierr);
8954a3e9fdbSToby Isaac   } else {
8964a3e9fdbSToby Isaac     ierr = DMFieldCreateFEGeom(coordField, pointIS, quad, faceData, geom);CHKERRQ(ierr);
8974a3e9fdbSToby Isaac     ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr);
8984a3e9fdbSToby Isaac     ierr = PetscContainerSetPointer(container, (void *) *geom);CHKERRQ(ierr);
8994a3e9fdbSToby Isaac     ierr = PetscContainerSetUserDestroy(container, PetscContainerUserDestroy_PetscFEGeom);CHKERRQ(ierr);
9004a3e9fdbSToby Isaac     ierr = PetscObjectCompose((PetscObject) pointIS, composeStr, (PetscObject) container);CHKERRQ(ierr);
9014a3e9fdbSToby Isaac     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
9024a3e9fdbSToby Isaac   }
9034a3e9fdbSToby Isaac   PetscFunctionReturn(0);
9044a3e9fdbSToby Isaac }
9054a3e9fdbSToby Isaac 
9064a3e9fdbSToby Isaac static PetscErrorCode DMSNESRestoreFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom)
9074a3e9fdbSToby Isaac {
9084a3e9fdbSToby Isaac   PetscFunctionBegin;
9094a3e9fdbSToby Isaac   *geom = NULL;
9107d4028c8SMatthew G. Knepley   PetscFunctionReturn(0);
9117d4028c8SMatthew G. Knepley }
9127d4028c8SMatthew G. Knepley 
91308449791SMatthew G. Knepley /*@
91408449791SMatthew G. Knepley   DMPlexSNESGetGeometryFVM - Return precomputed geometric data
91508449791SMatthew G. Knepley 
91608449791SMatthew G. Knepley   Input Parameter:
91708449791SMatthew G. Knepley . dm - The DM
91808449791SMatthew G. Knepley 
91908449791SMatthew G. Knepley   Output Parameters:
92008449791SMatthew G. Knepley + facegeom - The values precomputed from face geometry
92108449791SMatthew G. Knepley . cellgeom - The values precomputed from cell geometry
92208449791SMatthew G. Knepley - minRadius - The minimum radius over the mesh of an inscribed sphere in a cell
92308449791SMatthew G. Knepley 
92408449791SMatthew G. Knepley   Level: developer
92508449791SMatthew G. Knepley 
92608449791SMatthew G. Knepley .seealso: DMPlexTSSetRHSFunctionLocal()
92708449791SMatthew G. Knepley @*/
92808449791SMatthew G. Knepley PetscErrorCode DMPlexSNESGetGeometryFVM(DM dm, Vec *facegeom, Vec *cellgeom, PetscReal *minRadius)
92924cdb843SMatthew G. Knepley {
9304b32e5bbSToby Isaac   DM             plex;
93124cdb843SMatthew G. Knepley   PetscErrorCode ierr;
93224cdb843SMatthew G. Knepley 
93324cdb843SMatthew G. Knepley   PetscFunctionBegin;
93408449791SMatthew G. Knepley   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
9354b32e5bbSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
9364b32e5bbSToby Isaac   ierr = DMPlexGetDataFVM(plex, NULL, cellgeom, facegeom, NULL);CHKERRQ(ierr);
9374b32e5bbSToby Isaac   if (minRadius) {ierr = DMPlexGetMinRadius(plex, minRadius);CHKERRQ(ierr);}
9384b32e5bbSToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
93924cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
94024cdb843SMatthew G. Knepley }
94124cdb843SMatthew G. Knepley 
942dbd489d2SMatthew G. Knepley /*@
94308449791SMatthew G. Knepley   DMPlexSNESGetGradientDM - Return gradient data layout
94408449791SMatthew G. Knepley 
94508449791SMatthew G. Knepley   Input Parameters:
94608449791SMatthew G. Knepley + dm - The DM
94708449791SMatthew G. Knepley - fv - The PetscFV
94808449791SMatthew G. Knepley 
94908449791SMatthew G. Knepley   Output Parameter:
95008449791SMatthew G. Knepley . dmGrad - The layout for gradient values
95108449791SMatthew G. Knepley 
95208449791SMatthew G. Knepley   Level: developer
95308449791SMatthew G. Knepley 
95408449791SMatthew G. Knepley .seealso: DMPlexSNESGetGeometryFVM()
95508449791SMatthew G. Knepley @*/
95608449791SMatthew G. Knepley PetscErrorCode DMPlexSNESGetGradientDM(DM dm, PetscFV fv, DM *dmGrad)
95724cdb843SMatthew G. Knepley {
9584b32e5bbSToby Isaac   DM             plex;
95908449791SMatthew G. Knepley   PetscBool      computeGradients;
96024cdb843SMatthew G. Knepley   PetscErrorCode ierr;
96124cdb843SMatthew G. Knepley 
96224cdb843SMatthew G. Knepley   PetscFunctionBegin;
96308449791SMatthew G. Knepley   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
96408449791SMatthew G. Knepley   PetscValidHeaderSpecific(fv,PETSCFV_CLASSID,2);
96508449791SMatthew G. Knepley   PetscValidPointer(dmGrad,3);
96608449791SMatthew G. Knepley   ierr = PetscFVGetComputeGradients(fv, &computeGradients);CHKERRQ(ierr);
96708449791SMatthew G. Knepley   if (!computeGradients) {*dmGrad = NULL; PetscFunctionReturn(0);}
9684b32e5bbSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
9694b32e5bbSToby Isaac   ierr = DMPlexGetDataFVM(plex, fv, NULL, NULL, dmGrad);CHKERRQ(ierr);
9704b32e5bbSToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
97108449791SMatthew G. Knepley   PetscFunctionReturn(0);
97208449791SMatthew G. Knepley }
97308449791SMatthew G. Knepley 
97408449791SMatthew G. Knepley /*@C
97508449791SMatthew G. Knepley   DMPlexGetCellFields - Retrieve the field values values for a chunk of cells
97608449791SMatthew G. Knepley 
97708449791SMatthew G. Knepley   Input Parameters:
97808449791SMatthew G. Knepley + dm     - The DM
9799044fa66SMatthew G. Knepley . cellIS - The cells to include
98008449791SMatthew G. Knepley . locX   - A local vector with the solution fields
98108449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL
98208449791SMatthew G. Knepley - locA   - A local vector with auxiliary fields, or NULL
98308449791SMatthew G. Knepley 
98408449791SMatthew G. Knepley   Output Parameters:
98508449791SMatthew G. Knepley + u   - The field coefficients
98608449791SMatthew G. Knepley . u_t - The fields derivative coefficients
98708449791SMatthew G. Knepley - a   - The auxiliary field coefficients
98808449791SMatthew G. Knepley 
98908449791SMatthew G. Knepley   Level: developer
99008449791SMatthew G. Knepley 
99108449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields()
99208449791SMatthew G. Knepley @*/
9939044fa66SMatthew G. Knepley PetscErrorCode DMPlexGetCellFields(DM dm, IS cellIS, Vec locX, Vec locX_t, Vec locA, PetscScalar **u, PetscScalar **u_t, PetscScalar **a)
99408449791SMatthew G. Knepley {
9959044fa66SMatthew G. Knepley   DM              plex, plexA = NULL;
99608449791SMatthew G. Knepley   PetscSection    section, sectionAux;
99708449791SMatthew G. Knepley   PetscDS         prob;
9989044fa66SMatthew G. Knepley   const PetscInt *cells;
9999044fa66SMatthew G. Knepley   PetscInt        cStart, cEnd, numCells, totDim, totDimAux, c;
100008449791SMatthew G. Knepley   PetscErrorCode  ierr;
100108449791SMatthew G. Knepley 
100208449791SMatthew G. Knepley   PetscFunctionBegin;
100308449791SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100408449791SMatthew G. Knepley   PetscValidHeaderSpecific(locX, VEC_CLASSID, 4);
100508449791SMatthew G. Knepley   if (locX_t) {PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 5);}
100608449791SMatthew G. Knepley   if (locA)   {PetscValidHeaderSpecific(locA, VEC_CLASSID, 6);}
100708449791SMatthew G. Knepley   PetscValidPointer(u, 7);
100808449791SMatthew G. Knepley   PetscValidPointer(u_t, 8);
100908449791SMatthew G. Knepley   PetscValidPointer(a, 9);
10109044fa66SMatthew G. Knepley   ierr = DMSNESConvertPlex(dm, &plex, PETSC_FALSE);CHKERRQ(ierr);
10119044fa66SMatthew G. Knepley   ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
101224cdb843SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
101324cdb843SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
101424cdb843SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
101508449791SMatthew G. Knepley   if (locA) {
10169044fa66SMatthew G. Knepley     DM      dmAux;
101708449791SMatthew G. Knepley     PetscDS probAux;
101808449791SMatthew G. Knepley 
101908449791SMatthew G. Knepley     ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr);
10209044fa66SMatthew G. Knepley     ierr = DMSNESConvertPlex(dmAux, &plexA, PETSC_FALSE);CHKERRQ(ierr);
102124cdb843SMatthew G. Knepley     ierr = DMGetDefaultSection(dmAux, &sectionAux);CHKERRQ(ierr);
102224cdb843SMatthew G. Knepley     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
102324cdb843SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
102424cdb843SMatthew G. Knepley   }
10259044fa66SMatthew G. Knepley   numCells = cEnd - cStart;
102669291d52SBarry Smith   ierr = DMGetWorkArray(dm, numCells*totDim, MPIU_SCALAR, u);CHKERRQ(ierr);
102769291d52SBarry Smith   if (locX_t) {ierr = DMGetWorkArray(dm, numCells*totDim, MPIU_SCALAR, u_t);CHKERRQ(ierr);} else {*u_t = NULL;}
102869291d52SBarry Smith   if (locA)   {ierr = DMGetWorkArray(dm, numCells*totDimAux, MPIU_SCALAR, a);CHKERRQ(ierr);} else {*a = NULL;}
102924cdb843SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
10309044fa66SMatthew G. Knepley     const PetscInt cell = cells ? cells[c] : c;
10319044fa66SMatthew G. Knepley     const PetscInt cind = c - cStart;
103208449791SMatthew G. Knepley     PetscScalar   *x = NULL, *x_t = NULL, *ul = *u, *ul_t = *u_t, *al = *a;
103324cdb843SMatthew G. Knepley     PetscInt       i;
103424cdb843SMatthew G. Knepley 
10359044fa66SMatthew G. Knepley     ierr = DMPlexVecGetClosure(plex, section, locX, cell, NULL, &x);CHKERRQ(ierr);
10369044fa66SMatthew G. Knepley     for (i = 0; i < totDim; ++i) ul[cind*totDim+i] = x[i];
10379044fa66SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(plex, section, locX, cell, NULL, &x);CHKERRQ(ierr);
103808449791SMatthew G. Knepley     if (locX_t) {
10399044fa66SMatthew G. Knepley       ierr = DMPlexVecGetClosure(plex, section, locX_t, cell, NULL, &x_t);CHKERRQ(ierr);
10409044fa66SMatthew G. Knepley       for (i = 0; i < totDim; ++i) ul_t[cind*totDim+i] = x_t[i];
10419044fa66SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(plex, section, locX_t, cell, NULL, &x_t);CHKERRQ(ierr);
104224cdb843SMatthew G. Knepley     }
104308449791SMatthew G. Knepley     if (locA) {
10449044fa66SMatthew G. Knepley       ierr = DMPlexVecGetClosure(plexA, sectionAux, locA, cell, NULL, &x);CHKERRQ(ierr);
10459044fa66SMatthew G. Knepley       for (i = 0; i < totDimAux; ++i) al[cind*totDimAux+i] = x[i];
10469044fa66SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(plexA, sectionAux, locA, cell, NULL, &x);CHKERRQ(ierr);
104724cdb843SMatthew G. Knepley     }
104824cdb843SMatthew G. Knepley   }
10499044fa66SMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
10509044fa66SMatthew G. Knepley   if (locA) {ierr = DMDestroy(&plexA);CHKERRQ(ierr);}
10519044fa66SMatthew G. Knepley   ierr = ISRestorePointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
105208449791SMatthew G. Knepley   PetscFunctionReturn(0);
105308449791SMatthew G. Knepley }
105424cdb843SMatthew G. Knepley 
105508449791SMatthew G. Knepley /*@C
105608449791SMatthew G. Knepley   DMPlexRestoreCellFields - Restore the field values values for a chunk of cells
105708449791SMatthew G. Knepley 
105808449791SMatthew G. Knepley   Input Parameters:
105908449791SMatthew G. Knepley + dm     - The DM
10609044fa66SMatthew G. Knepley . cellIS - The cells to include
106108449791SMatthew G. Knepley . locX   - A local vector with the solution fields
106208449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL
106308449791SMatthew G. Knepley - locA   - A local vector with auxiliary fields, or NULL
106408449791SMatthew G. Knepley 
106508449791SMatthew G. Knepley   Output Parameters:
106608449791SMatthew G. Knepley + u   - The field coefficients
106708449791SMatthew G. Knepley . u_t - The fields derivative coefficients
106808449791SMatthew G. Knepley - a   - The auxiliary field coefficients
106908449791SMatthew G. Knepley 
107008449791SMatthew G. Knepley   Level: developer
107108449791SMatthew G. Knepley 
107208449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields()
107308449791SMatthew G. Knepley @*/
10749044fa66SMatthew G. Knepley PetscErrorCode DMPlexRestoreCellFields(DM dm, IS cellIS, Vec locX, Vec locX_t, Vec locA, PetscScalar **u, PetscScalar **u_t, PetscScalar **a)
107508449791SMatthew G. Knepley {
107608449791SMatthew G. Knepley   PetscErrorCode ierr;
107708449791SMatthew G. Knepley 
107808449791SMatthew G. Knepley   PetscFunctionBegin;
107969291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, u);CHKERRQ(ierr);
1080040f60c8SVaclav Hapla   if (locX_t) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, u_t);CHKERRQ(ierr);}
1081040f60c8SVaclav Hapla   if (locA)   {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, a);CHKERRQ(ierr);}
108208449791SMatthew G. Knepley   PetscFunctionReturn(0);
108324cdb843SMatthew G. Knepley }
108408449791SMatthew G. Knepley 
108508449791SMatthew G. Knepley /*@C
108608449791SMatthew G. Knepley   DMPlexGetFaceFields - Retrieve the field values values for a chunk of faces
108708449791SMatthew G. Knepley 
108808449791SMatthew G. Knepley   Input Parameters:
108908449791SMatthew G. Knepley + dm     - The DM
109008449791SMatthew G. Knepley . fStart - The first face to include
109108449791SMatthew G. Knepley . fEnd   - The first face to exclude
109208449791SMatthew G. Knepley . locX   - A local vector with the solution fields
109308449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL
109408449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry
109508449791SMatthew G. Knepley . cellGeometry - A local vector with cell geometry
109608449791SMatthew G. Knepley - locaGrad - A local vector with field gradients, or NULL
109708449791SMatthew G. Knepley 
109808449791SMatthew G. Knepley   Output Parameters:
10995f942ad5SMatthew G. Knepley + Nface - The number of faces with field values
11005f942ad5SMatthew G. Knepley . uL - The field values at the left side of the face
1101477f7dfdSMatthew G. Knepley - uR - The field values at the right side of the face
110208449791SMatthew G. Knepley 
110308449791SMatthew G. Knepley   Level: developer
110408449791SMatthew G. Knepley 
110508449791SMatthew G. Knepley .seealso: DMPlexGetCellFields()
110608449791SMatthew G. Knepley @*/
11075f942ad5SMatthew G. Knepley PetscErrorCode DMPlexGetFaceFields(DM dm, PetscInt fStart, PetscInt fEnd, Vec locX, Vec locX_t, Vec faceGeometry, Vec cellGeometry, Vec locGrad, PetscInt *Nface, PetscScalar **uL, PetscScalar **uR)
110808449791SMatthew G. Knepley {
110908449791SMatthew G. Knepley   DM                 dmFace, dmCell, dmGrad = NULL;
1110195142f5SMatthew G. Knepley   PetscSection       section;
111108449791SMatthew G. Knepley   PetscDS            prob;
111208449791SMatthew G. Knepley   DMLabel            ghostLabel;
111308449791SMatthew G. Knepley   const PetscScalar *facegeom, *cellgeom, *x, *lgrad;
1114477f7dfdSMatthew G. Knepley   PetscBool         *isFE;
1115477f7dfdSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, numFaces = fEnd - fStart, iface, face;
111608449791SMatthew G. Knepley   PetscErrorCode     ierr;
111708449791SMatthew G. Knepley 
111808449791SMatthew G. Knepley   PetscFunctionBegin;
111908449791SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
112008449791SMatthew G. Knepley   PetscValidHeaderSpecific(locX, VEC_CLASSID, 4);
112108449791SMatthew G. Knepley   if (locX_t) {PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 5);}
112208449791SMatthew G. Knepley   PetscValidHeaderSpecific(faceGeometry, VEC_CLASSID, 6);
112308449791SMatthew G. Knepley   PetscValidHeaderSpecific(cellGeometry, VEC_CLASSID, 7);
112408449791SMatthew G. Knepley   if (locGrad) {PetscValidHeaderSpecific(locGrad, VEC_CLASSID, 8);}
112508449791SMatthew G. Knepley   PetscValidPointer(uL, 9);
112608449791SMatthew G. Knepley   PetscValidPointer(uR, 10);
112708449791SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
112808449791SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
1129195142f5SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1130477f7dfdSMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
1131477f7dfdSMatthew G. Knepley   ierr = PetscDSGetTotalComponents(prob, &Nc);CHKERRQ(ierr);
1132477f7dfdSMatthew G. Knepley   ierr = PetscMalloc1(Nf, &isFE);CHKERRQ(ierr);
1133477f7dfdSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
1134477f7dfdSMatthew G. Knepley     PetscObject  obj;
1135477f7dfdSMatthew G. Knepley     PetscClassId id;
1136477f7dfdSMatthew G. Knepley 
11374a270516SSander Arens     ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
1138477f7dfdSMatthew G. Knepley     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
1139477f7dfdSMatthew G. Knepley     if (id == PETSCFE_CLASSID)      {isFE[f] = PETSC_TRUE;}
1140477f7dfdSMatthew G. Knepley     else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;}
1141477f7dfdSMatthew G. Knepley     else                            {isFE[f] = PETSC_FALSE;}
1142477f7dfdSMatthew G. Knepley   }
1143c58f1c22SToby Isaac   ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr);
114408449791SMatthew G. Knepley   ierr = VecGetArrayRead(locX, &x);CHKERRQ(ierr);
114508449791SMatthew G. Knepley   ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr);
114608449791SMatthew G. Knepley   ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr);
114708449791SMatthew G. Knepley   ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr);
114808449791SMatthew G. Knepley   ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr);
114908449791SMatthew G. Knepley   if (locGrad) {
115008449791SMatthew G. Knepley     ierr = VecGetDM(locGrad, &dmGrad);CHKERRQ(ierr);
115108449791SMatthew G. Knepley     ierr = VecGetArrayRead(locGrad, &lgrad);CHKERRQ(ierr);
115224cdb843SMatthew G. Knepley   }
115369291d52SBarry Smith   ierr = DMGetWorkArray(dm, numFaces*Nc, MPIU_SCALAR, uL);CHKERRQ(ierr);
115469291d52SBarry Smith   ierr = DMGetWorkArray(dm, numFaces*Nc, MPIU_SCALAR, uR);CHKERRQ(ierr);
1155477f7dfdSMatthew G. Knepley   /* Right now just eat the extra work for FE (could make a cell loop) */
115608449791SMatthew G. Knepley   for (face = fStart, iface = 0; face < fEnd; ++face) {
115708449791SMatthew G. Knepley     const PetscInt        *cells;
1158640bce14SSatish Balay     PetscFVFaceGeom       *fg;
1159640bce14SSatish Balay     PetscFVCellGeom       *cgL, *cgR;
1160640bce14SSatish Balay     PetscScalar           *xL, *xR, *gL, *gR;
116108449791SMatthew G. Knepley     PetscScalar           *uLl = *uL, *uRl = *uR;
11623e64cd2fSToby Isaac     PetscInt               ghost, nsupp, nchild;
116308449791SMatthew G. Knepley 
116408449791SMatthew G. Knepley     ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr);
1165e697831aSToby Isaac     ierr = DMPlexGetSupportSize(dm, face, &nsupp);CHKERRQ(ierr);
11663e64cd2fSToby Isaac     ierr = DMPlexGetTreeChildren(dm, face, &nchild, NULL);CHKERRQ(ierr);
11677c45b140SToby Isaac     if (ghost >= 0 || nsupp > 2 || nchild > 0) continue;
116808449791SMatthew G. Knepley     ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr);
116908449791SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr);
117008449791SMatthew G. Knepley     ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cgL);CHKERRQ(ierr);
117108449791SMatthew G. Knepley     ierr = DMPlexPointLocalRead(dmCell, cells[1], cellgeom, &cgR);CHKERRQ(ierr);
1172477f7dfdSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
1173477f7dfdSMatthew G. Knepley       PetscInt off;
1174477f7dfdSMatthew G. Knepley 
117537a43ebbSMatthew G. Knepley       ierr = PetscDSGetComponentOffset(prob, f, &off);CHKERRQ(ierr);
1176477f7dfdSMatthew G. Knepley       if (isFE[f]) {
1177477f7dfdSMatthew G. Knepley         const PetscInt *cone;
11783e64cd2fSToby Isaac         PetscInt        comp, coneSizeL, coneSizeR, faceLocL, faceLocR, ldof, rdof, d;
1179477f7dfdSMatthew G. Knepley 
1180cca9989dSMatthew G. Knepley         xL = xR = NULL;
11817c45b140SToby Isaac         ierr = PetscSectionGetFieldComponents(section, f, &comp);CHKERRQ(ierr);
1182cca9989dSMatthew G. Knepley         ierr = DMPlexVecGetClosure(dm, section, locX, cells[0], &ldof, (PetscScalar **) &xL);CHKERRQ(ierr);
1183cca9989dSMatthew G. Knepley         ierr = DMPlexVecGetClosure(dm, section, locX, cells[1], &rdof, (PetscScalar **) &xR);CHKERRQ(ierr);
1184477f7dfdSMatthew G. Knepley         ierr = DMPlexGetCone(dm, cells[0], &cone);CHKERRQ(ierr);
11853e64cd2fSToby Isaac         ierr = DMPlexGetConeSize(dm, cells[0], &coneSizeL);CHKERRQ(ierr);
11863e64cd2fSToby Isaac         for (faceLocL = 0; faceLocL < coneSizeL; ++faceLocL) if (cone[faceLocL] == face) break;
1187477f7dfdSMatthew G. Knepley         ierr = DMPlexGetCone(dm, cells[1], &cone);CHKERRQ(ierr);
11883e64cd2fSToby Isaac         ierr = DMPlexGetConeSize(dm, cells[1], &coneSizeR);CHKERRQ(ierr);
11893e64cd2fSToby Isaac         for (faceLocR = 0; faceLocR < coneSizeR; ++faceLocR) if (cone[faceLocR] == face) break;
11903e64cd2fSToby Isaac         if (faceLocL == coneSizeL && faceLocR == coneSizeR) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d or cell %d", face, cells[0], cells[1]);
1191195142f5SMatthew G. Knepley         /* Check that FEM field has values in the right cell (sometimes its an FV ghost cell) */
11923e64cd2fSToby Isaac         /* TODO: this is a hack that might not be right for nonconforming */
11933e64cd2fSToby Isaac         if (faceLocL < coneSizeL) {
1194477f7dfdSMatthew G. Knepley           ierr = EvaluateFaceFields(prob, f, faceLocL, xL, &uLl[iface*Nc+off]);CHKERRQ(ierr);
11953e64cd2fSToby Isaac           if (rdof == ldof && faceLocR < coneSizeR) {ierr = EvaluateFaceFields(prob, f, faceLocR, xR, &uRl[iface*Nc+off]);CHKERRQ(ierr);}
11967c45b140SToby Isaac           else              {for(d = 0; d < comp; ++d) uRl[iface*Nc+off+d] = uLl[iface*Nc+off+d];}
11973e64cd2fSToby Isaac         }
11983e64cd2fSToby Isaac         else {
11993e64cd2fSToby Isaac           ierr = EvaluateFaceFields(prob, f, faceLocR, xR, &uRl[iface*Nc+off]);CHKERRQ(ierr);
12003e64cd2fSToby Isaac           ierr = PetscSectionGetFieldComponents(section, f, &comp);CHKERRQ(ierr);
12013e64cd2fSToby Isaac           for(d = 0; d < comp; ++d) uLl[iface*Nc+off+d] = uRl[iface*Nc+off+d];
12023e64cd2fSToby Isaac         }
1203cca9989dSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(dm, section, locX, cells[0], &ldof, (PetscScalar **) &xL);CHKERRQ(ierr);
1204cca9989dSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(dm, section, locX, cells[1], &rdof, (PetscScalar **) &xR);CHKERRQ(ierr);
1205477f7dfdSMatthew G. Knepley       } else {
1206477f7dfdSMatthew G. Knepley         PetscFV  fv;
1207477f7dfdSMatthew G. Knepley         PetscInt numComp, c;
1208477f7dfdSMatthew G. Knepley 
1209477f7dfdSMatthew G. Knepley         ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fv);CHKERRQ(ierr);
1210477f7dfdSMatthew G. Knepley         ierr = PetscFVGetNumComponents(fv, &numComp);CHKERRQ(ierr);
1211cca9989dSMatthew G. Knepley         ierr = DMPlexPointLocalFieldRead(dm, cells[0], f, x, &xL);CHKERRQ(ierr);
1212cca9989dSMatthew G. Knepley         ierr = DMPlexPointLocalFieldRead(dm, cells[1], f, x, &xR);CHKERRQ(ierr);
121308449791SMatthew G. Knepley         if (dmGrad) {
121408449791SMatthew G. Knepley           PetscReal dxL[3], dxR[3];
121508449791SMatthew G. Knepley 
121608449791SMatthew G. Knepley           ierr = DMPlexPointLocalRead(dmGrad, cells[0], lgrad, &gL);CHKERRQ(ierr);
121708449791SMatthew G. Knepley           ierr = DMPlexPointLocalRead(dmGrad, cells[1], lgrad, &gR);CHKERRQ(ierr);
121808449791SMatthew G. Knepley           DMPlex_WaxpyD_Internal(dim, -1, cgL->centroid, fg->centroid, dxL);
121908449791SMatthew G. Knepley           DMPlex_WaxpyD_Internal(dim, -1, cgR->centroid, fg->centroid, dxR);
1220477f7dfdSMatthew G. Knepley           for (c = 0; c < numComp; ++c) {
1221477f7dfdSMatthew G. Knepley             uLl[iface*Nc+off+c] = xL[c] + DMPlex_DotD_Internal(dim, &gL[c*dim], dxL);
1222477f7dfdSMatthew G. Knepley             uRl[iface*Nc+off+c] = xR[c] + DMPlex_DotD_Internal(dim, &gR[c*dim], dxR);
122308449791SMatthew G. Knepley           }
122408449791SMatthew G. Knepley         } else {
1225477f7dfdSMatthew G. Knepley           for (c = 0; c < numComp; ++c) {
1226477f7dfdSMatthew G. Knepley             uLl[iface*Nc+off+c] = xL[c];
1227477f7dfdSMatthew G. Knepley             uRl[iface*Nc+off+c] = xR[c];
1228477f7dfdSMatthew G. Knepley           }
1229477f7dfdSMatthew G. Knepley         }
123008449791SMatthew G. Knepley       }
123108449791SMatthew G. Knepley     }
123208449791SMatthew G. Knepley     ++iface;
123308449791SMatthew G. Knepley   }
12345f942ad5SMatthew G. Knepley   *Nface = iface;
123508449791SMatthew G. Knepley   ierr = VecRestoreArrayRead(locX, &x);CHKERRQ(ierr);
123608449791SMatthew G. Knepley   ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr);
123708449791SMatthew G. Knepley   ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr);
123808449791SMatthew G. Knepley   if (locGrad) {
123908449791SMatthew G. Knepley     ierr = VecRestoreArrayRead(locGrad, &lgrad);CHKERRQ(ierr);
124008449791SMatthew G. Knepley   }
1241477f7dfdSMatthew G. Knepley   ierr = PetscFree(isFE);CHKERRQ(ierr);
124208449791SMatthew G. Knepley   PetscFunctionReturn(0);
124308449791SMatthew G. Knepley }
124408449791SMatthew G. Knepley 
124508449791SMatthew G. Knepley /*@C
124608449791SMatthew G. Knepley   DMPlexRestoreFaceFields - Restore the field values values for a chunk of faces
124708449791SMatthew G. Knepley 
124808449791SMatthew G. Knepley   Input Parameters:
124908449791SMatthew G. Knepley + dm     - The DM
125008449791SMatthew G. Knepley . fStart - The first face to include
125108449791SMatthew G. Knepley . fEnd   - The first face to exclude
125208449791SMatthew G. Knepley . locX   - A local vector with the solution fields
125308449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL
125408449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry
125508449791SMatthew G. Knepley . cellGeometry - A local vector with cell geometry
125608449791SMatthew G. Knepley - locaGrad - A local vector with field gradients, or NULL
125708449791SMatthew G. Knepley 
125808449791SMatthew G. Knepley   Output Parameters:
12595f942ad5SMatthew G. Knepley + Nface - The number of faces with field values
12605f942ad5SMatthew G. Knepley . uL - The field values at the left side of the face
1261477f7dfdSMatthew G. Knepley - uR - The field values at the right side of the face
126208449791SMatthew G. Knepley 
126308449791SMatthew G. Knepley   Level: developer
126408449791SMatthew G. Knepley 
126508449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields()
126608449791SMatthew G. Knepley @*/
12675f942ad5SMatthew G. Knepley PetscErrorCode DMPlexRestoreFaceFields(DM dm, PetscInt fStart, PetscInt fEnd, Vec locX, Vec locX_t, Vec faceGeometry, Vec cellGeometry, Vec locGrad, PetscInt *Nface, PetscScalar **uL, PetscScalar **uR)
126808449791SMatthew G. Knepley {
126908449791SMatthew G. Knepley   PetscErrorCode ierr;
127008449791SMatthew G. Knepley 
127108449791SMatthew G. Knepley   PetscFunctionBegin;
127269291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, uL);CHKERRQ(ierr);
127369291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, uR);CHKERRQ(ierr);
127408449791SMatthew G. Knepley   PetscFunctionReturn(0);
127508449791SMatthew G. Knepley }
127608449791SMatthew G. Knepley 
127708449791SMatthew G. Knepley /*@C
127808449791SMatthew G. Knepley   DMPlexGetFaceGeometry - Retrieve the geometric values for a chunk of faces
127908449791SMatthew G. Knepley 
128008449791SMatthew G. Knepley   Input Parameters:
128108449791SMatthew G. Knepley + dm     - The DM
128208449791SMatthew G. Knepley . fStart - The first face to include
128308449791SMatthew G. Knepley . fEnd   - The first face to exclude
128408449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry
128508449791SMatthew G. Knepley - cellGeometry - A local vector with cell geometry
128608449791SMatthew G. Knepley 
128708449791SMatthew G. Knepley   Output Parameters:
12885f942ad5SMatthew G. Knepley + Nface - The number of faces with field values
12895f942ad5SMatthew G. Knepley . fgeom - The extract the face centroid and normal
129008449791SMatthew G. Knepley - vol   - The cell volume
129108449791SMatthew G. Knepley 
129208449791SMatthew G. Knepley   Level: developer
129308449791SMatthew G. Knepley 
129408449791SMatthew G. Knepley .seealso: DMPlexGetCellFields()
129508449791SMatthew G. Knepley @*/
12965f942ad5SMatthew G. Knepley PetscErrorCode DMPlexGetFaceGeometry(DM dm, PetscInt fStart, PetscInt fEnd, Vec faceGeometry, Vec cellGeometry, PetscInt *Nface, PetscFVFaceGeom **fgeom, PetscReal **vol)
129708449791SMatthew G. Knepley {
129808449791SMatthew G. Knepley   DM                 dmFace, dmCell;
129908449791SMatthew G. Knepley   DMLabel            ghostLabel;
130008449791SMatthew G. Knepley   const PetscScalar *facegeom, *cellgeom;
130108449791SMatthew G. Knepley   PetscInt           dim, numFaces = fEnd - fStart, iface, face;
130208449791SMatthew G. Knepley   PetscErrorCode     ierr;
130308449791SMatthew G. Knepley 
130408449791SMatthew G. Knepley   PetscFunctionBegin;
130508449791SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
130608449791SMatthew G. Knepley   PetscValidHeaderSpecific(faceGeometry, VEC_CLASSID, 4);
130708449791SMatthew G. Knepley   PetscValidHeaderSpecific(cellGeometry, VEC_CLASSID, 5);
130808449791SMatthew G. Knepley   PetscValidPointer(fgeom, 6);
130908449791SMatthew G. Knepley   PetscValidPointer(vol, 7);
131008449791SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1311c58f1c22SToby Isaac   ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr);
131208449791SMatthew G. Knepley   ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr);
131308449791SMatthew G. Knepley   ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr);
131408449791SMatthew G. Knepley   ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr);
131508449791SMatthew G. Knepley   ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr);
131608449791SMatthew G. Knepley   ierr = PetscMalloc1(numFaces, fgeom);CHKERRQ(ierr);
131769291d52SBarry Smith   ierr = DMGetWorkArray(dm, numFaces*2, MPIU_SCALAR, vol);CHKERRQ(ierr);
131808449791SMatthew G. Knepley   for (face = fStart, iface = 0; face < fEnd; ++face) {
131908449791SMatthew G. Knepley     const PetscInt        *cells;
1320640bce14SSatish Balay     PetscFVFaceGeom       *fg;
1321640bce14SSatish Balay     PetscFVCellGeom       *cgL, *cgR;
132208449791SMatthew G. Knepley     PetscFVFaceGeom       *fgeoml = *fgeom;
13232eefff9cSMatthew G. Knepley     PetscReal             *voll   = *vol;
13247c45b140SToby Isaac     PetscInt               ghost, d, nchild, nsupp;
132508449791SMatthew G. Knepley 
132608449791SMatthew G. Knepley     ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr);
13277c45b140SToby Isaac     ierr = DMPlexGetSupportSize(dm, face, &nsupp);CHKERRQ(ierr);
13287c45b140SToby Isaac     ierr = DMPlexGetTreeChildren(dm, face, &nchild, NULL);CHKERRQ(ierr);
13297c45b140SToby Isaac     if (ghost >= 0 || nsupp > 2 || nchild > 0) continue;
133008449791SMatthew G. Knepley     ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr);
133108449791SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr);
133208449791SMatthew G. Knepley     ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cgL);CHKERRQ(ierr);
133308449791SMatthew G. Knepley     ierr = DMPlexPointLocalRead(dmCell, cells[1], cellgeom, &cgR);CHKERRQ(ierr);
133408449791SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
133508449791SMatthew G. Knepley       fgeoml[iface].centroid[d] = fg->centroid[d];
133608449791SMatthew G. Knepley       fgeoml[iface].normal[d]   = fg->normal[d];
133708449791SMatthew G. Knepley     }
133808449791SMatthew G. Knepley     voll[iface*2+0] = cgL->volume;
133908449791SMatthew G. Knepley     voll[iface*2+1] = cgR->volume;
134008449791SMatthew G. Knepley     ++iface;
134108449791SMatthew G. Knepley   }
13425f942ad5SMatthew G. Knepley   *Nface = iface;
134308449791SMatthew G. Knepley   ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr);
134408449791SMatthew G. Knepley   ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr);
134508449791SMatthew G. Knepley   PetscFunctionReturn(0);
134608449791SMatthew G. Knepley }
134708449791SMatthew G. Knepley 
134808449791SMatthew G. Knepley /*@C
134908449791SMatthew G. Knepley   DMPlexRestoreFaceGeometry - Restore the field values values for a chunk of faces
135008449791SMatthew G. Knepley 
135108449791SMatthew G. Knepley   Input Parameters:
135208449791SMatthew G. Knepley + dm     - The DM
135308449791SMatthew G. Knepley . fStart - The first face to include
135408449791SMatthew G. Knepley . fEnd   - The first face to exclude
135508449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry
135608449791SMatthew G. Knepley - cellGeometry - A local vector with cell geometry
135708449791SMatthew G. Knepley 
135808449791SMatthew G. Knepley   Output Parameters:
13595f942ad5SMatthew G. Knepley + Nface - The number of faces with field values
13605f942ad5SMatthew G. Knepley . fgeom - The extract the face centroid and normal
136108449791SMatthew G. Knepley - vol   - The cell volume
136208449791SMatthew G. Knepley 
136308449791SMatthew G. Knepley   Level: developer
136408449791SMatthew G. Knepley 
136508449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields()
136608449791SMatthew G. Knepley @*/
13675f942ad5SMatthew G. Knepley PetscErrorCode DMPlexRestoreFaceGeometry(DM dm, PetscInt fStart, PetscInt fEnd, Vec faceGeometry, Vec cellGeometry, PetscInt *Nface, PetscFVFaceGeom **fgeom, PetscReal **vol)
136808449791SMatthew G. Knepley {
136908449791SMatthew G. Knepley   PetscErrorCode ierr;
137008449791SMatthew G. Knepley 
137108449791SMatthew G. Knepley   PetscFunctionBegin;
137208449791SMatthew G. Knepley   ierr = PetscFree(*fgeom);CHKERRQ(ierr);
137369291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, vol);CHKERRQ(ierr);
137408449791SMatthew G. Knepley   PetscFunctionReturn(0);
137508449791SMatthew G. Knepley }
137608449791SMatthew G. Knepley 
13774a3e9fdbSToby Isaac static PetscErrorCode ISIntersect_Caching(IS is1, IS is2, IS *isect)
137808449791SMatthew G. Knepley {
137908449791SMatthew G. Knepley   PetscErrorCode ierr;
138008449791SMatthew G. Knepley 
138108449791SMatthew G. Knepley   PetscFunctionBegin;
13824a3e9fdbSToby Isaac   *isect = NULL;
13834a3e9fdbSToby Isaac   if (is2 && is1) {
13844a3e9fdbSToby Isaac     char           composeStr[33] = {0};
13854a3e9fdbSToby Isaac     PetscObjectId  is2id;
13864a3e9fdbSToby Isaac 
13874a3e9fdbSToby Isaac     ierr = PetscObjectGetId((PetscObject)is2,&is2id);CHKERRQ(ierr);
13884a3e9fdbSToby Isaac     ierr = PetscSNPrintf(composeStr,32,"ISIntersect_Caching_%x",is2id);CHKERRQ(ierr);
13894a3e9fdbSToby Isaac     ierr = PetscObjectQuery((PetscObject) is1, composeStr, (PetscObject *) isect);CHKERRQ(ierr);
13904a3e9fdbSToby Isaac     if (*isect == NULL) {
13914a3e9fdbSToby Isaac       ierr = ISIntersect(is1, is2, isect);CHKERRQ(ierr);
13924a3e9fdbSToby Isaac       ierr = PetscObjectCompose((PetscObject) is1, composeStr, (PetscObject) *isect);CHKERRQ(ierr);
13934a3e9fdbSToby Isaac     } else {
13944a3e9fdbSToby Isaac       ierr = PetscObjectReference((PetscObject) *isect);CHKERRQ(ierr);
13954a3e9fdbSToby Isaac     }
13964a3e9fdbSToby Isaac   }
13974a3e9fdbSToby Isaac   PetscFunctionReturn(0);
13984a3e9fdbSToby Isaac }
13994a3e9fdbSToby Isaac 
1400c330f8ffSToby Isaac static PetscErrorCode DMPlexComputeBdResidual_Single_Internal(DM dm, PetscReal t, DMLabel label, PetscInt numValues, const PetscInt values[], PetscInt field, Vec locX, Vec locX_t, Vec locF, DMField coordField, IS facetIS)
140108449791SMatthew G. Knepley {
140208449791SMatthew G. Knepley   DM_Plex         *mesh = (DM_Plex *) dm->data;
1403023fee6eSMatthew G. Knepley   DM               plex = NULL, plexA = NULL;
140408449791SMatthew G. Knepley   PetscDS          prob, probAux = NULL;
140508449791SMatthew G. Knepley   PetscSection     section, sectionAux = NULL;
140608449791SMatthew G. Knepley   Vec              locA = NULL;
1407c330f8ffSToby Isaac   PetscFEGeom     *fgeom;
140808449791SMatthew G. Knepley   PetscScalar     *u = NULL, *u_t = NULL, *a = NULL, *elemVec = NULL;
140908449791SMatthew G. Knepley   PetscInt         v;
1410c330f8ffSToby Isaac   PetscInt         totDim, totDimAux = 0;
141108449791SMatthew G. Knepley   PetscErrorCode   ierr;
141208449791SMatthew G. Knepley 
141308449791SMatthew G. Knepley   PetscFunctionBegin;
1414023fee6eSMatthew G. Knepley   ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr);
14154236e4b7SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
141608449791SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
14174d0b9603SSander Arens   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
14182d91c981SSander Arens   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &locA);CHKERRQ(ierr);
14192d91c981SSander Arens   if (locA) {
14204236e4b7SMatthew G. Knepley     DM dmAux;
14214236e4b7SMatthew G. Knepley 
14222d91c981SSander Arens     ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr);
1423023fee6eSMatthew G. Knepley     ierr = DMConvert(dmAux, DMPLEX, &plexA);CHKERRQ(ierr);
1424023fee6eSMatthew G. Knepley     ierr = DMGetDS(plexA, &probAux);CHKERRQ(ierr);
14254d0b9603SSander Arens     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
1426023fee6eSMatthew G. Knepley     ierr = DMGetDefaultSection(plexA, &sectionAux);CHKERRQ(ierr);
14272d91c981SSander Arens   }
14284236e4b7SMatthew G. Knepley   for (v = 0; v < numValues; ++v) {
1429c330f8ffSToby Isaac     PetscBool        isAffine;
1430c330f8ffSToby Isaac     PetscQuadrature  qGeom = NULL;
143124cdb843SMatthew G. Knepley     IS               pointIS;
143224cdb843SMatthew G. Knepley     const PetscInt  *points;
1433f74ed4f0SToby Isaac     PetscInt         numFaces, face, Nq;
143424cdb843SMatthew G. Knepley 
1435a8e83e26SSanderA     ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr);
143622734eb1Ssarens     if (!pointIS) continue; /* No points with that id on this process */
1437c330f8ffSToby Isaac     {
1438c330f8ffSToby Isaac       IS isectIS;
1439c330f8ffSToby Isaac 
14404a3e9fdbSToby Isaac       /* TODO: Special cases of ISIntersect where it is quick to check a priori if one is a superset of the other */
14414a3e9fdbSToby Isaac       ierr = ISIntersect_Caching(facetIS,pointIS,&isectIS);CHKERRQ(ierr);
1442c330f8ffSToby Isaac       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1443c330f8ffSToby Isaac       pointIS = isectIS;
144424cdb843SMatthew G. Knepley     }
1445c330f8ffSToby Isaac     ierr = ISGetLocalSize(pointIS,&numFaces);CHKERRQ(ierr);
1446c330f8ffSToby Isaac     ierr = ISGetIndices(pointIS,&points);CHKERRQ(ierr);
1447c330f8ffSToby Isaac     ierr = PetscMalloc4(numFaces*totDim, &u, locX_t ? numFaces*totDim : 0, &u_t, numFaces*totDim, &elemVec, locA ? numFaces*totDimAux : 0, &a);CHKERRQ(ierr);
1448c330f8ffSToby Isaac     ierr = DMFieldGetFEInvariance(coordField,pointIS,NULL,&isAffine,NULL);CHKERRQ(ierr);
1449c330f8ffSToby Isaac     if (isAffine) {
1450c330f8ffSToby Isaac       ierr = DMFieldCreateDefaultQuadrature(coordField,pointIS,&qGeom);CHKERRQ(ierr);
1451c330f8ffSToby Isaac     }
1452c330f8ffSToby Isaac     if (!qGeom) {
1453c330f8ffSToby Isaac       PetscFE fe;
1454c330f8ffSToby Isaac 
1455c330f8ffSToby Isaac       ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
1456c330f8ffSToby Isaac       ierr = PetscFEGetFaceQuadrature(fe, &qGeom);CHKERRQ(ierr);
1457c330f8ffSToby Isaac       ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr);
1458c330f8ffSToby Isaac     }
1459c330f8ffSToby Isaac     ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
14604a3e9fdbSToby Isaac     ierr = DMSNESGetFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr);
1461c330f8ffSToby Isaac     for (face = 0; face < numFaces; ++face) {
1462c330f8ffSToby Isaac       const PetscInt point = points[face], *support, *cone;
146324cdb843SMatthew G. Knepley       PetscScalar   *x     = NULL;
14649bfb2fe4SJed Brown       PetscInt       i, coneSize, faceLoc;
146524cdb843SMatthew G. Knepley 
14664d0b9603SSander Arens       ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr);
14674d0b9603SSander Arens       ierr = DMPlexGetConeSize(dm, support[0], &coneSize);CHKERRQ(ierr);
14684d0b9603SSander Arens       ierr = DMPlexGetCone(dm, support[0], &cone);CHKERRQ(ierr);
14694d0b9603SSander Arens       for (faceLoc = 0; faceLoc < coneSize; ++faceLoc) if (cone[faceLoc] == point) break;
14704236e4b7SMatthew G. Knepley       if (faceLoc == coneSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of support[0] %D", point, support[0]);
1471c330f8ffSToby Isaac       fgeom->face[face][0] = faceLoc;
14724d0b9603SSander Arens       ierr = DMPlexVecGetClosure(dm, section, locX, support[0], NULL, &x);CHKERRQ(ierr);
14734d0b9603SSander Arens       for (i = 0; i < totDim; ++i) u[face*totDim+i] = x[i];
1474023fee6eSMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(plex, section, locX, support[0], NULL, &x);CHKERRQ(ierr);
147508449791SMatthew G. Knepley       if (locX_t) {
1476023fee6eSMatthew G. Knepley         ierr = DMPlexVecGetClosure(plex, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr);
14774d0b9603SSander Arens         for (i = 0; i < totDim; ++i) u_t[face*totDim+i] = x[i];
1478023fee6eSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(plex, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr);
147924cdb843SMatthew G. Knepley       }
14802d91c981SSander Arens       if (locA) {
1481023fee6eSMatthew G. Knepley         PetscInt subp;
1482023fee6eSMatthew G. Knepley         ierr = DMPlexGetSubpoint(plexA, support[0], &subp);CHKERRQ(ierr);
1483023fee6eSMatthew G. Knepley         ierr = DMPlexVecGetClosure(plexA, sectionAux, locA, subp, NULL, &x);CHKERRQ(ierr);
14844d0b9603SSander Arens         for (i = 0; i < totDimAux; ++i) a[face*totDimAux+i] = x[i];
1485023fee6eSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(plexA, sectionAux, locA, subp, NULL, &x);CHKERRQ(ierr);
148624cdb843SMatthew G. Knepley       }
148724cdb843SMatthew G. Knepley     }
14884d0b9603SSander Arens     ierr = PetscMemzero(elemVec, numFaces*totDim * sizeof(PetscScalar));CHKERRQ(ierr);
1489cbf52bb1SSander Arens     {
149024cdb843SMatthew G. Knepley       PetscFE         fe;
1491f74ed4f0SToby Isaac       PetscInt        Nb;
1492c330f8ffSToby Isaac       PetscFEGeom     *chunkGeom = NULL;
149324cdb843SMatthew G. Knepley       /* Conforming batches */
149424cdb843SMatthew G. Knepley       PetscInt        numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
149524cdb843SMatthew G. Knepley       /* Remainder */
149624cdb843SMatthew G. Knepley       PetscInt        Nr, offset;
149724cdb843SMatthew G. Knepley 
14984d0b9603SSander Arens       ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
149924cdb843SMatthew G. Knepley       ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
150024cdb843SMatthew G. Knepley       ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
1501c330f8ffSToby Isaac       /* TODO: documentation is unclear about what is going on with these numbers: how should Nb / Nq factor in ? */
1502c330f8ffSToby Isaac       blockSize = Nb;
150324cdb843SMatthew G. Knepley       batchSize = numBlocks * blockSize;
150424cdb843SMatthew G. Knepley       ierr =  PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
150524cdb843SMatthew G. Knepley       numChunks = numFaces / (numBatches*batchSize);
150624cdb843SMatthew G. Knepley       Ne        = numChunks*numBatches*batchSize;
150724cdb843SMatthew G. Knepley       Nr        = numFaces % (numBatches*batchSize);
150824cdb843SMatthew G. Knepley       offset    = numFaces - Nr;
1509c330f8ffSToby Isaac       ierr = PetscFEGeomGetChunk(fgeom,0,offset,&chunkGeom);CHKERRQ(ierr);
1510c330f8ffSToby Isaac       ierr = PetscFEIntegrateBdResidual(fe, prob, field, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec);CHKERRQ(ierr);
1511c330f8ffSToby Isaac       ierr = PetscFEGeomGetChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr);
1512c330f8ffSToby Isaac       ierr = PetscFEIntegrateBdResidual(fe, prob, field, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, a ? &a[offset*totDimAux] : NULL, t, &elemVec[offset*totDim]);CHKERRQ(ierr);
1513c330f8ffSToby Isaac       ierr = PetscFEGeomRestoreChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr);
151424cdb843SMatthew G. Knepley     }
1515c330f8ffSToby Isaac     for (face = 0; face < numFaces; ++face) {
1516c330f8ffSToby Isaac       const PetscInt point = points[face], *support;
151724cdb843SMatthew G. Knepley 
15184d0b9603SSander Arens       if (mesh->printFEM > 1) {ierr = DMPrintCellVector(point, "BdResidual", totDim, &elemVec[face*totDim]);CHKERRQ(ierr);}
1519023fee6eSMatthew G. Knepley       ierr = DMPlexGetSupport(plex, point, &support);CHKERRQ(ierr);
1520023fee6eSMatthew G. Knepley       ierr = DMPlexVecSetClosure(plex, NULL, locF, support[0], &elemVec[face*totDim], ADD_ALL_VALUES);CHKERRQ(ierr);
152124cdb843SMatthew G. Knepley     }
15224a3e9fdbSToby Isaac     ierr = DMSNESRestoreFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr);
1523c330f8ffSToby Isaac     ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr);
152424cdb843SMatthew G. Knepley     ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
152524cdb843SMatthew G. Knepley     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1526c330f8ffSToby Isaac     ierr = PetscFree4(u, u_t, elemVec, a);CHKERRQ(ierr);
152724cdb843SMatthew G. Knepley   }
1528023fee6eSMatthew G. Knepley   if (plex)  {ierr = DMDestroy(&plex);CHKERRQ(ierr);}
1529023fee6eSMatthew G. Knepley   if (plexA) {ierr = DMDestroy(&plexA);CHKERRQ(ierr);}
15304236e4b7SMatthew G. Knepley   PetscFunctionReturn(0);
1531a8e83e26SSanderA }
15324236e4b7SMatthew G. Knepley 
15334236e4b7SMatthew G. Knepley PetscErrorCode DMPlexComputeBdResidual_Internal(DM dm, Vec locX, Vec locX_t, PetscReal t, Vec locF, void *user)
15344236e4b7SMatthew G. Knepley {
15354236e4b7SMatthew G. Knepley   PetscDS        prob;
1536a179f353SToby Isaac   PetscInt       dim, numBd, bd;
1537a179f353SToby Isaac   DMLabel        depthLabel;
1538c330f8ffSToby Isaac   DMField        coordField = NULL;
1539c330f8ffSToby Isaac   IS             facetIS;
15404236e4b7SMatthew G. Knepley   PetscErrorCode ierr;
15414236e4b7SMatthew G. Knepley 
15424236e4b7SMatthew G. Knepley   PetscFunctionBegin;
15434236e4b7SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
1544a179f353SToby Isaac   ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr);
1545c330f8ffSToby Isaac   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1546a179f353SToby Isaac   ierr = DMLabelGetStratumIS(depthLabel,dim - 1,&facetIS);CHKERRQ(ierr);
15474236e4b7SMatthew G. Knepley   ierr = PetscDSGetNumBoundary(prob, &numBd);CHKERRQ(ierr);
15484a3e9fdbSToby Isaac   ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr);
15494236e4b7SMatthew G. Knepley   for (bd = 0; bd < numBd; ++bd) {
15504236e4b7SMatthew G. Knepley     DMBoundaryConditionType type;
15514236e4b7SMatthew G. Knepley     const char             *bdLabel;
15524236e4b7SMatthew G. Knepley     DMLabel                 label;
15534236e4b7SMatthew G. Knepley     const PetscInt         *values;
15544236e4b7SMatthew G. Knepley     PetscInt                field, numValues;
15554236e4b7SMatthew G. Knepley     PetscObject             obj;
15564236e4b7SMatthew G. Knepley     PetscClassId            id;
15574236e4b7SMatthew G. Knepley 
15584236e4b7SMatthew G. Knepley     ierr = PetscDSGetBoundary(prob, bd, &type, NULL, &bdLabel, &field, NULL, NULL, NULL, &numValues, &values, NULL);CHKERRQ(ierr);
15594236e4b7SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
15604236e4b7SMatthew G. Knepley     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
15614236e4b7SMatthew G. Knepley     if ((id != PETSCFE_CLASSID) || (type & DM_BC_ESSENTIAL)) continue;
15624236e4b7SMatthew G. Knepley     ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr);
1563c330f8ffSToby Isaac     ierr = DMPlexComputeBdResidual_Single_Internal(dm, t, label, numValues, values, field, locX, locX_t, locF, coordField, facetIS);CHKERRQ(ierr);
15644236e4b7SMatthew G. Knepley   }
1565c330f8ffSToby Isaac   ierr = ISDestroy(&facetIS);CHKERRQ(ierr);
156608449791SMatthew G. Knepley   PetscFunctionReturn(0);
156708449791SMatthew G. Knepley }
156808449791SMatthew G. Knepley 
15694a3e9fdbSToby Isaac PetscErrorCode DMPlexComputeResidual_Internal(DM dm, IS cellIS, PetscReal time, Vec locX, Vec locX_t, PetscReal t, Vec locF, void *user)
157008449791SMatthew G. Knepley {
157108449791SMatthew G. Knepley   DM_Plex         *mesh       = (DM_Plex *) dm->data;
157208449791SMatthew G. Knepley   const char      *name       = "Residual";
157308449791SMatthew G. Knepley   DM               dmAux      = NULL;
157408449791SMatthew G. Knepley   DM               dmGrad     = NULL;
157508449791SMatthew G. Knepley   DMLabel          ghostLabel = NULL;
157608449791SMatthew G. Knepley   PetscDS          prob       = NULL;
157708449791SMatthew G. Knepley   PetscDS          probAux    = NULL;
157808449791SMatthew G. Knepley   PetscSection     section    = NULL;
157908449791SMatthew G. Knepley   PetscBool        useFEM     = PETSC_FALSE;
158008449791SMatthew G. Knepley   PetscBool        useFVM     = PETSC_FALSE;
1581b2666ceaSMatthew G. Knepley   PetscBool        isImplicit = (locX_t || time == PETSC_MIN_REAL) ? PETSC_TRUE : PETSC_FALSE;
158208449791SMatthew G. Knepley   PetscFV          fvm        = NULL;
158308449791SMatthew G. Knepley   PetscFVCellGeom *cgeomFVM   = NULL;
158408449791SMatthew G. Knepley   PetscFVFaceGeom *fgeomFVM   = NULL;
1585c330f8ffSToby Isaac   DMField          coordField = NULL;
1586c330f8ffSToby Isaac   Vec              locA, cellGeometryFVM = NULL, faceGeometryFVM = NULL, grad, locGrad = NULL;
15873755293bSMatthew G. Knepley   PetscScalar     *u = NULL, *u_t, *a, *uL, *uR;
15889044fa66SMatthew G. Knepley   IS               chunkIS;
15899044fa66SMatthew G. Knepley   const PetscInt  *cells;
15909044fa66SMatthew G. Knepley   PetscInt         cStart, cEnd, numCells;
1591c4d4a4f8SMatthew G. Knepley   PetscInt         Nf, f, totDim, totDimAux, numChunks, cellChunkSize, faceChunkSize, chunk, fStart, fEnd;
15924a3e9fdbSToby Isaac   PetscBool        isAffine = PETSC_FALSE;
15934a3e9fdbSToby Isaac   PetscQuadrature  affineQuad = NULL, *quads = NULL;
15944a3e9fdbSToby Isaac   PetscFEGeom     *affineGeom = NULL, **geoms = NULL;
159508449791SMatthew G. Knepley   PetscErrorCode   ierr;
159608449791SMatthew G. Knepley 
159708449791SMatthew G. Knepley   PetscFunctionBegin;
159808449791SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr);
159908449791SMatthew G. Knepley   /* TODO The places where we have to use isFE are probably the member functions for the PetscDisc class */
1600195142f5SMatthew G. Knepley   /* TODO The FVM geometry is over-manipulated. Make the precalc functions return exactly what we need */
160108449791SMatthew G. Knepley   /* FEM+FVM */
160208449791SMatthew G. Knepley   /* 1: Get sizes from dm and dmAux */
160308449791SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1604c58f1c22SToby Isaac   ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr);
160508449791SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
160608449791SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
160708449791SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
160808449791SMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &locA);CHKERRQ(ierr);
160908449791SMatthew G. Knepley   if (locA) {
161008449791SMatthew G. Knepley     ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr);
161108449791SMatthew G. Knepley     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
161208449791SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
161308449791SMatthew G. Knepley   }
161408449791SMatthew G. Knepley   /* 2: Get geometric data */
161508449791SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
161608449791SMatthew G. Knepley     PetscObject  obj;
161708449791SMatthew G. Knepley     PetscClassId id;
16187173168dSMatthew G. Knepley     PetscBool    fimp;
161908449791SMatthew G. Knepley 
16207173168dSMatthew G. Knepley     ierr = PetscDSGetImplicit(prob, f, &fimp);CHKERRQ(ierr);
16217173168dSMatthew G. Knepley     if (isImplicit != fimp) continue;
162208449791SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
162308449791SMatthew G. Knepley     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
162408449791SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {useFEM = PETSC_TRUE;}
162508449791SMatthew G. Knepley     if (id == PETSCFV_CLASSID) {useFVM = PETSC_TRUE; fvm = (PetscFV) obj;}
162608449791SMatthew G. Knepley   }
162708449791SMatthew G. Knepley   if (useFEM) {
16284a3e9fdbSToby Isaac     ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr);
16294a3e9fdbSToby Isaac     ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr);
16304a3e9fdbSToby Isaac     if (isAffine) {
16314a3e9fdbSToby Isaac       ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&affineQuad);CHKERRQ(ierr);
1632741db25dSToby Isaac       if (affineQuad) {
16334a3e9fdbSToby Isaac         ierr = DMSNESGetFEGeom(coordField,cellIS,affineQuad,PETSC_FALSE,&affineGeom);CHKERRQ(ierr);
1634741db25dSToby Isaac       }
16354a3e9fdbSToby Isaac     } else {
16364a3e9fdbSToby Isaac       ierr = PetscCalloc2(Nf,&quads,Nf,&geoms);CHKERRQ(ierr);
16374a3e9fdbSToby Isaac       for (f = 0; f < Nf; ++f) {
16384a3e9fdbSToby Isaac         PetscObject  obj;
16394a3e9fdbSToby Isaac         PetscClassId id;
16404a3e9fdbSToby Isaac         PetscBool    fimp;
16412f84e9bcSToby Isaac 
16424a3e9fdbSToby Isaac         ierr = PetscDSGetImplicit(prob, f, &fimp);CHKERRQ(ierr);
16434a3e9fdbSToby Isaac         if (isImplicit != fimp) continue;
16444a3e9fdbSToby Isaac         ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
16454a3e9fdbSToby Isaac         ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
16464a3e9fdbSToby Isaac         if (id == PETSCFE_CLASSID) {
16474a3e9fdbSToby Isaac           PetscFE fe = (PetscFE) obj;
16482f84e9bcSToby Isaac 
16494a3e9fdbSToby Isaac           ierr = PetscFEGetQuadrature(fe, &quads[f]);CHKERRQ(ierr);
16504a3e9fdbSToby Isaac           ierr = PetscObjectReference((PetscObject)quads[f]);CHKERRQ(ierr);
16514a3e9fdbSToby Isaac           ierr = DMSNESGetFEGeom(coordField,cellIS,quads[f],PETSC_FALSE,&geoms[f]);CHKERRQ(ierr);
16522f84e9bcSToby Isaac         }
16532f84e9bcSToby Isaac       }
16542f84e9bcSToby Isaac     }
165508449791SMatthew G. Knepley   }
165608449791SMatthew G. Knepley   if (useFVM) {
165708449791SMatthew G. Knepley     ierr = DMPlexSNESGetGeometryFVM(dm, &faceGeometryFVM, &cellGeometryFVM, NULL);CHKERRQ(ierr);
165808449791SMatthew G. Knepley     ierr = VecGetArrayRead(faceGeometryFVM, (const PetscScalar **) &fgeomFVM);CHKERRQ(ierr);
165908449791SMatthew G. Knepley     ierr = VecGetArrayRead(cellGeometryFVM, (const PetscScalar **) &cgeomFVM);CHKERRQ(ierr);
166008449791SMatthew G. Knepley     /* Reconstruct and limit cell gradients */
166108449791SMatthew G. Knepley     ierr = DMPlexSNESGetGradientDM(dm, fvm, &dmGrad);CHKERRQ(ierr);
166208449791SMatthew G. Knepley     if (dmGrad) {
166308449791SMatthew G. Knepley       ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
166408449791SMatthew G. Knepley       ierr = DMGetGlobalVector(dmGrad, &grad);CHKERRQ(ierr);
1665de555695SMatthew G. Knepley       ierr = DMPlexReconstructGradients_Internal(dm, fvm, fStart, fEnd, faceGeometryFVM, cellGeometryFVM, locX, grad);CHKERRQ(ierr);
166608449791SMatthew G. Knepley       /* Communicate gradient values */
166708449791SMatthew G. Knepley       ierr = DMGetLocalVector(dmGrad, &locGrad);CHKERRQ(ierr);
166808449791SMatthew G. Knepley       ierr = DMGlobalToLocalBegin(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr);
166908449791SMatthew G. Knepley       ierr = DMGlobalToLocalEnd(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr);
167008449791SMatthew G. Knepley       ierr = DMRestoreGlobalVector(dmGrad, &grad);CHKERRQ(ierr);
167108449791SMatthew G. Knepley     }
1672bdd6f66aSToby Isaac     /* Handle non-essential (e.g. outflow) boundary values */
1673bdd6f66aSToby Isaac     ierr = DMPlexInsertBoundaryValues(dm, PETSC_FALSE, locX, time, faceGeometryFVM, cellGeometryFVM, locGrad);CHKERRQ(ierr);
167408449791SMatthew G. Knepley   }
167508449791SMatthew G. Knepley   /* Loop over chunks */
16769044fa66SMatthew G. Knepley   ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
167708449791SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
16789044fa66SMatthew G. Knepley   if (useFEM) {ierr = ISCreate(PETSC_COMM_SELF, &chunkIS);CHKERRQ(ierr);}
16799044fa66SMatthew G. Knepley   numCells      = cEnd - cStart;
168008449791SMatthew G. Knepley   numChunks     = 1;
16814a3e9fdbSToby Isaac   cellChunkSize = numCells/numChunks;
168208449791SMatthew G. Knepley   faceChunkSize = (fEnd - fStart)/numChunks;
1683741db25dSToby Isaac   numChunks     = PetscMin(1,numCells);
168408449791SMatthew G. Knepley   for (chunk = 0; chunk < numChunks; ++chunk) {
16852eefff9cSMatthew G. Knepley     PetscScalar     *elemVec, *fluxL, *fluxR;
16862eefff9cSMatthew G. Knepley     PetscReal       *vol;
168708449791SMatthew G. Knepley     PetscFVFaceGeom *fgeom;
16889044fa66SMatthew G. Knepley     PetscInt         cS = cStart+chunk*cellChunkSize, cE = PetscMin(cS+cellChunkSize, cEnd), numCells = cE - cS, c;
16893755293bSMatthew G. Knepley     PetscInt         fS = fStart+chunk*faceChunkSize, fE = PetscMin(fS+faceChunkSize, fEnd), numFaces = 0, face;
169008449791SMatthew G. Knepley 
169108449791SMatthew G. Knepley     /* Extract field coefficients */
169208449791SMatthew G. Knepley     if (useFEM) {
16939044fa66SMatthew G. Knepley       ierr = ISGetPointSubrange(chunkIS, cS, cE, cells);CHKERRQ(ierr);
16949044fa66SMatthew G. Knepley       ierr = DMPlexGetCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a);CHKERRQ(ierr);
169569291d52SBarry Smith       ierr = DMGetWorkArray(dm, numCells*totDim, MPIU_SCALAR, &elemVec);CHKERRQ(ierr);
1696215c4595SMatthew G. Knepley       ierr = PetscMemzero(elemVec, numCells*totDim * sizeof(PetscScalar));CHKERRQ(ierr);
169708449791SMatthew G. Knepley     }
169808449791SMatthew G. Knepley     if (useFVM) {
16995f942ad5SMatthew G. Knepley       ierr = DMPlexGetFaceFields(dm, fS, fE, locX, locX_t, faceGeometryFVM, cellGeometryFVM, locGrad, &numFaces, &uL, &uR);CHKERRQ(ierr);
17005f942ad5SMatthew G. Knepley       ierr = DMPlexGetFaceGeometry(dm, fS, fE, faceGeometryFVM, cellGeometryFVM, &numFaces, &fgeom, &vol);CHKERRQ(ierr);
170169291d52SBarry Smith       ierr = DMGetWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxL);CHKERRQ(ierr);
170269291d52SBarry Smith       ierr = DMGetWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxR);CHKERRQ(ierr);
1703215c4595SMatthew G. Knepley       ierr = PetscMemzero(fluxL, numFaces*totDim * sizeof(PetscScalar));CHKERRQ(ierr);
1704215c4595SMatthew G. Knepley       ierr = PetscMemzero(fluxR, numFaces*totDim * sizeof(PetscScalar));CHKERRQ(ierr);
170508449791SMatthew G. Knepley     }
170608449791SMatthew G. Knepley     /* TODO We will interlace both our field coefficients (u, u_t, uL, uR, etc.) and our output (elemVec, fL, fR). I think this works */
170708449791SMatthew G. Knepley     /* Loop over fields */
170808449791SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
170908449791SMatthew G. Knepley       PetscObject  obj;
171008449791SMatthew G. Knepley       PetscClassId id;
17117173168dSMatthew G. Knepley       PetscBool    fimp;
171208449791SMatthew G. Knepley       PetscInt     numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset;
171308449791SMatthew G. Knepley 
17147173168dSMatthew G. Knepley       ierr = PetscDSGetImplicit(prob, f, &fimp);CHKERRQ(ierr);
17157173168dSMatthew G. Knepley       if (isImplicit != fimp) continue;
171608449791SMatthew G. Knepley       ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
171708449791SMatthew G. Knepley       ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
171808449791SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
171908449791SMatthew G. Knepley         PetscFE         fe = (PetscFE) obj;
17204a3e9fdbSToby Isaac         PetscFEGeom    *geom = affineGeom ? affineGeom : geoms[f];
17214a3e9fdbSToby Isaac         PetscFEGeom    *chunkGeom = NULL;
17224a3e9fdbSToby Isaac         PetscQuadrature quad = affineQuad ? affineQuad : quads[f];
172308449791SMatthew G. Knepley         PetscInt        Nq, Nb;
172408449791SMatthew G. Knepley 
172508449791SMatthew G. Knepley         ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
17264a3e9fdbSToby Isaac         ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
172708449791SMatthew G. Knepley         ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
1728c330f8ffSToby Isaac         blockSize = Nb;
172908449791SMatthew G. Knepley         batchSize = numBlocks * blockSize;
173008449791SMatthew G. Knepley         ierr      = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
173108449791SMatthew G. Knepley         numChunks = numCells / (numBatches*batchSize);
173208449791SMatthew G. Knepley         Ne        = numChunks*numBatches*batchSize;
173308449791SMatthew G. Knepley         Nr        = numCells % (numBatches*batchSize);
173408449791SMatthew G. Knepley         offset    = numCells - Nr;
173508449791SMatthew G. Knepley         /* Integrate FE residual to get elemVec (need fields at quadrature points) */
173608449791SMatthew G. Knepley         /*   For FV, I think we use a P0 basis and the cell coefficients (for subdivided cells, we can tweak the basis tabulation to be the indicator function) */
17374a3e9fdbSToby Isaac         ierr = PetscFEGeomGetChunk(geom,0,offset,&chunkGeom);CHKERRQ(ierr);
1738c330f8ffSToby Isaac         ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec);CHKERRQ(ierr);
17394a3e9fdbSToby Isaac         ierr = PetscFEGeomGetChunk(geom,offset,numCells,&chunkGeom);CHKERRQ(ierr);
1740c330f8ffSToby Isaac         ierr = PetscFEIntegrateResidual(fe, prob, f, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, &elemVec[offset*totDim]);CHKERRQ(ierr);
17414a3e9fdbSToby Isaac         ierr = PetscFEGeomRestoreChunk(geom,offset,numCells,&chunkGeom);CHKERRQ(ierr);
174208449791SMatthew G. Knepley       } else if (id == PETSCFV_CLASSID) {
174308449791SMatthew G. Knepley         PetscFV fv = (PetscFV) obj;
174408449791SMatthew G. Knepley 
174508449791SMatthew G. Knepley         Ne = numFaces;
174608449791SMatthew G. Knepley         /* Riemann solve over faces (need fields at face centroids) */
174708449791SMatthew G. Knepley         /*   We need to evaluate FE fields at those coordinates */
174808449791SMatthew G. Knepley         ierr = PetscFVIntegrateRHSFunction(fv, prob, f, Ne, fgeom, vol, uL, uR, fluxL, fluxR);CHKERRQ(ierr);
174908449791SMatthew G. Knepley       } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
175008449791SMatthew G. Knepley     }
175108449791SMatthew G. Knepley     /* Loop over domain */
175208449791SMatthew G. Knepley     if (useFEM) {
175308449791SMatthew G. Knepley       /* Add elemVec to locX */
17549044fa66SMatthew G. Knepley       for (c = cS; c < cE; ++c) {
17559044fa66SMatthew G. Knepley         const PetscInt cell = cells ? cells[c] : c;
17569044fa66SMatthew G. Knepley         const PetscInt cind = c - cStart;
1757f905620eSMatthew G. Knepley 
17589044fa66SMatthew G. Knepley         if (mesh->printFEM > 1) {ierr = DMPrintCellVector(cell, name, totDim, &elemVec[cind*totDim]);CHKERRQ(ierr);}
1759b4920ed3SToby Isaac         if (ghostLabel) {
1760b4920ed3SToby Isaac           PetscInt ghostVal;
1761b4920ed3SToby Isaac 
1762b4920ed3SToby Isaac           ierr = DMLabelGetValue(ghostLabel,cell,&ghostVal);CHKERRQ(ierr);
1763b4920ed3SToby Isaac           if (ghostVal > 0) continue;
1764b4920ed3SToby Isaac         }
17659044fa66SMatthew G. Knepley         ierr = DMPlexVecSetClosure(dm, section, locF, cell, &elemVec[cind*totDim], ADD_ALL_VALUES);CHKERRQ(ierr);
176608449791SMatthew G. Knepley       }
176708449791SMatthew G. Knepley     }
176808449791SMatthew G. Knepley     if (useFVM) {
17694a394323SMatthew G. Knepley       PetscScalar *fa;
177008449791SMatthew G. Knepley       PetscInt     iface;
177108449791SMatthew G. Knepley 
177208449791SMatthew G. Knepley       ierr = VecGetArray(locF, &fa);CHKERRQ(ierr);
1773c10b5f1bSMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
1774c10b5f1bSMatthew G. Knepley         PetscFV      fv;
1775c10b5f1bSMatthew G. Knepley         PetscObject  obj;
1776c10b5f1bSMatthew G. Knepley         PetscClassId id;
17774a394323SMatthew G. Knepley         PetscInt     foff, pdim;
1778c10b5f1bSMatthew G. Knepley 
1779c10b5f1bSMatthew G. Knepley         ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
1780c10b5f1bSMatthew G. Knepley         ierr = PetscDSGetFieldOffset(prob, f, &foff);CHKERRQ(ierr);
1781c10b5f1bSMatthew G. Knepley         ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
1782c10b5f1bSMatthew G. Knepley         if (id != PETSCFV_CLASSID) continue;
1783c10b5f1bSMatthew G. Knepley         fv   = (PetscFV) obj;
1784c10b5f1bSMatthew G. Knepley         ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr);
1785c10b5f1bSMatthew G. Knepley         /* Accumulate fluxes to cells */
178608449791SMatthew G. Knepley         for (face = fS, iface = 0; face < fE; ++face) {
17879044fa66SMatthew G. Knepley           const PetscInt *scells;
1788b4920ed3SToby Isaac           PetscScalar    *fL = NULL, *fR = NULL;
17897c45b140SToby Isaac           PetscInt        ghost, d, nsupp, nchild;
179008449791SMatthew G. Knepley 
179108449791SMatthew G. Knepley           ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr);
1792ffe9ad51SToby Isaac           ierr = DMPlexGetSupportSize(dm, face, &nsupp);CHKERRQ(ierr);
17937c45b140SToby Isaac           ierr = DMPlexGetTreeChildren(dm, face, &nchild, NULL);CHKERRQ(ierr);
17947c45b140SToby Isaac           if (ghost >= 0 || nsupp > 2 || nchild > 0) continue;
17959044fa66SMatthew G. Knepley           ierr = DMPlexGetSupport(dm, face, &scells);CHKERRQ(ierr);
17969044fa66SMatthew G. Knepley           ierr = DMLabelGetValue(ghostLabel,scells[0],&ghost);CHKERRQ(ierr);
17979044fa66SMatthew G. Knepley           if (ghost <= 0) {ierr = DMPlexPointLocalFieldRef(dm, scells[0], f, fa, &fL);CHKERRQ(ierr);}
17989044fa66SMatthew G. Knepley           ierr = DMLabelGetValue(ghostLabel,scells[1],&ghost);CHKERRQ(ierr);
17999044fa66SMatthew G. Knepley           if (ghost <= 0) {ierr = DMPlexPointLocalFieldRef(dm, scells[1], f, fa, &fR);CHKERRQ(ierr);}
1800c10b5f1bSMatthew G. Knepley           for (d = 0; d < pdim; ++d) {
1801c10b5f1bSMatthew G. Knepley             if (fL) fL[d] -= fluxL[iface*totDim+foff+d];
1802c10b5f1bSMatthew G. Knepley             if (fR) fR[d] += fluxR[iface*totDim+foff+d];
180308449791SMatthew G. Knepley           }
180408449791SMatthew G. Knepley           ++iface;
180508449791SMatthew G. Knepley         }
1806dab51205SMatthew G. Knepley       }
1807dab51205SMatthew G. Knepley       ierr = VecRestoreArray(locF, &fa);CHKERRQ(ierr);
1808dab51205SMatthew G. Knepley     }
1809c10b5f1bSMatthew G. Knepley     /* Handle time derivative */
1810c10b5f1bSMatthew G. Knepley     if (locX_t) {
1811dab51205SMatthew G. Knepley       PetscScalar *x_t, *fa;
1812dab51205SMatthew G. Knepley 
1813dab51205SMatthew G. Knepley       ierr = VecGetArray(locF, &fa);CHKERRQ(ierr);
1814c10b5f1bSMatthew G. Knepley       ierr = VecGetArray(locX_t, &x_t);CHKERRQ(ierr);
1815dab51205SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
1816dab51205SMatthew G. Knepley         PetscFV      fv;
1817dab51205SMatthew G. Knepley         PetscObject  obj;
1818dab51205SMatthew G. Knepley         PetscClassId id;
1819dab51205SMatthew G. Knepley         PetscInt     pdim, d;
1820dab51205SMatthew G. Knepley 
1821dab51205SMatthew G. Knepley         ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
1822dab51205SMatthew G. Knepley         ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
1823dab51205SMatthew G. Knepley         if (id != PETSCFV_CLASSID) continue;
1824dab51205SMatthew G. Knepley         fv   = (PetscFV) obj;
1825dab51205SMatthew G. Knepley         ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr);
18269044fa66SMatthew G. Knepley         for (c = cS; c < cE; ++c) {
18279044fa66SMatthew G. Knepley           const PetscInt cell = cells ? cells[c] : c;
1828c10b5f1bSMatthew G. Knepley           PetscScalar   *u_t, *r;
1829c10b5f1bSMatthew G. Knepley 
1830b4920ed3SToby Isaac           if (ghostLabel) {
1831b4920ed3SToby Isaac             PetscInt ghostVal;
1832b4920ed3SToby Isaac 
1833b4920ed3SToby Isaac             ierr = DMLabelGetValue(ghostLabel, cell, &ghostVal);CHKERRQ(ierr);
1834b4920ed3SToby Isaac             if (ghostVal > 0) continue;
1835b4920ed3SToby Isaac           }
1836c10b5f1bSMatthew G. Knepley           ierr = DMPlexPointLocalFieldRead(dm, cell, f, x_t, &u_t);CHKERRQ(ierr);
1837c10b5f1bSMatthew G. Knepley           ierr = DMPlexPointLocalFieldRef(dm, cell, f, fa, &r);CHKERRQ(ierr);
1838d63b37e5SMatthew G. Knepley           for (d = 0; d < pdim; ++d) r[d] += u_t[d];
1839c10b5f1bSMatthew G. Knepley         }
1840dab51205SMatthew G. Knepley       }
1841c10b5f1bSMatthew G. Knepley       ierr = VecRestoreArray(locX_t, &x_t);CHKERRQ(ierr);
184208449791SMatthew G. Knepley       ierr = VecRestoreArray(locF, &fa);CHKERRQ(ierr);
184308449791SMatthew G. Knepley     }
184408449791SMatthew G. Knepley     if (useFEM) {
18459044fa66SMatthew G. Knepley       ierr = DMPlexRestoreCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a);CHKERRQ(ierr);
184669291d52SBarry Smith       ierr = DMRestoreWorkArray(dm, numCells*totDim, MPIU_SCALAR, &elemVec);CHKERRQ(ierr);
184708449791SMatthew G. Knepley     }
184808449791SMatthew G. Knepley     if (useFVM) {
18495f942ad5SMatthew G. Knepley       ierr = DMPlexRestoreFaceFields(dm, fS, fE, locX, locX_t, faceGeometryFVM, cellGeometryFVM, locGrad, &numFaces, &uL, &uR);CHKERRQ(ierr);
18505f942ad5SMatthew G. Knepley       ierr = DMPlexRestoreFaceGeometry(dm, fS, fE, faceGeometryFVM, cellGeometryFVM, &numFaces, &fgeom, &vol);CHKERRQ(ierr);
185169291d52SBarry Smith       ierr = DMRestoreWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxL);CHKERRQ(ierr);
185269291d52SBarry Smith       ierr = DMRestoreWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxR);CHKERRQ(ierr);
185308449791SMatthew G. Knepley       if (dmGrad) {ierr = DMRestoreLocalVector(dmGrad, &locGrad);CHKERRQ(ierr);}
185408449791SMatthew G. Knepley     }
185508449791SMatthew G. Knepley   }
185603fee3f0SMatthew G. Knepley   if (useFEM) {ierr = ISDestroy(&chunkIS);CHKERRQ(ierr);}
18579044fa66SMatthew G. Knepley   ierr = ISRestorePointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
185808449791SMatthew G. Knepley 
18594a3e9fdbSToby Isaac   if (useFEM) {
18604a3e9fdbSToby Isaac     ierr = DMPlexComputeBdResidual_Internal(dm, locX, locX_t, t, locF, user);CHKERRQ(ierr);
18614a3e9fdbSToby Isaac 
18624a3e9fdbSToby Isaac     if (isAffine) {
18634a3e9fdbSToby Isaac       ierr = DMSNESRestoreFEGeom(coordField,cellIS,affineQuad,PETSC_FALSE,&affineGeom);CHKERRQ(ierr);
18644a3e9fdbSToby Isaac       ierr = PetscQuadratureDestroy(&affineQuad);CHKERRQ(ierr);
18654a3e9fdbSToby Isaac     } else {
18664a3e9fdbSToby Isaac       for (f = 0; f < Nf; ++f) {
18674a3e9fdbSToby Isaac         ierr = DMSNESRestoreFEGeom(coordField,cellIS,quads[f],PETSC_FALSE,&geoms[f]);CHKERRQ(ierr);
18684a3e9fdbSToby Isaac         ierr = PetscQuadratureDestroy(&quads[f]);CHKERRQ(ierr);
18694a3e9fdbSToby Isaac       }
18704a3e9fdbSToby Isaac       ierr = PetscFree2(quads,geoms);CHKERRQ(ierr);
18714a3e9fdbSToby Isaac     }
18724a3e9fdbSToby Isaac   }
187308449791SMatthew G. Knepley 
187408449791SMatthew G. Knepley   /* FEM */
187508449791SMatthew G. Knepley   /* 1: Get sizes from dm and dmAux */
187608449791SMatthew G. Knepley   /* 2: Get geometric data */
187708449791SMatthew G. Knepley   /* 3: Handle boundary values */
187808449791SMatthew G. Knepley   /* 4: Loop over domain */
187908449791SMatthew G. Knepley   /*   Extract coefficients */
188008449791SMatthew G. Knepley   /* Loop over fields */
188108449791SMatthew G. Knepley   /*   Set tiling for FE*/
188208449791SMatthew G. Knepley   /*   Integrate FE residual to get elemVec */
188308449791SMatthew G. Knepley   /*     Loop over subdomain */
188408449791SMatthew G. Knepley   /*       Loop over quad points */
188508449791SMatthew G. Knepley   /*         Transform coords to real space */
188608449791SMatthew G. Knepley   /*         Evaluate field and aux fields at point */
188708449791SMatthew G. Knepley   /*         Evaluate residual at point */
188808449791SMatthew G. Knepley   /*         Transform residual to real space */
188908449791SMatthew G. Knepley   /*       Add residual to elemVec */
189008449791SMatthew G. Knepley   /* Loop over domain */
189108449791SMatthew G. Knepley   /*   Add elemVec to locX */
189208449791SMatthew G. Knepley 
189308449791SMatthew G. Knepley   /* FVM */
189408449791SMatthew G. Knepley   /* Get geometric data */
189508449791SMatthew G. Knepley   /* If using gradients */
189608449791SMatthew G. Knepley   /*   Compute gradient data */
189708449791SMatthew G. Knepley   /*   Loop over domain faces */
189808449791SMatthew G. Knepley   /*     Count computational faces */
189908449791SMatthew G. Knepley   /*     Reconstruct cell gradient */
190008449791SMatthew G. Knepley   /*   Loop over domain cells */
190108449791SMatthew G. Knepley   /*     Limit cell gradients */
190208449791SMatthew G. Knepley   /* Handle boundary values */
190308449791SMatthew G. Knepley   /* Loop over domain faces */
190408449791SMatthew G. Knepley   /*   Read out field, centroid, normal, volume for each side of face */
190508449791SMatthew G. Knepley   /* Riemann solve over faces */
190608449791SMatthew G. Knepley   /* Loop over domain faces */
190708449791SMatthew G. Knepley   /*   Accumulate fluxes to cells */
190808449791SMatthew G. Knepley   /* TODO Change printFEM to printDisc here */
1909247ba720SToby Isaac   if (mesh->printFEM) {
1910247ba720SToby Isaac     Vec         locFbc;
1911247ba720SToby Isaac     PetscInt    pStart, pEnd, p, maxDof;
1912247ba720SToby Isaac     PetscScalar *zeroes;
1913247ba720SToby Isaac 
1914247ba720SToby Isaac     ierr = VecDuplicate(locF,&locFbc);CHKERRQ(ierr);
1915247ba720SToby Isaac     ierr = VecCopy(locF,locFbc);CHKERRQ(ierr);
1916247ba720SToby Isaac     ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr);
1917247ba720SToby Isaac     ierr = PetscSectionGetMaxDof(section,&maxDof);CHKERRQ(ierr);
1918247ba720SToby Isaac     ierr = PetscCalloc1(maxDof,&zeroes);CHKERRQ(ierr);
1919247ba720SToby Isaac     for (p = pStart; p < pEnd; p++) {
1920247ba720SToby Isaac       ierr = VecSetValuesSection(locFbc,section,p,zeroes,INSERT_BC_VALUES);CHKERRQ(ierr);
1921247ba720SToby Isaac     }
1922247ba720SToby Isaac     ierr = PetscFree(zeroes);CHKERRQ(ierr);
1923247ba720SToby Isaac     ierr = DMPrintLocalVec(dm, name, mesh->printTol, locFbc);CHKERRQ(ierr);
1924247ba720SToby Isaac     ierr = VecDestroy(&locFbc);CHKERRQ(ierr);
1925247ba720SToby Isaac   }
192624cdb843SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr);
192724cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
192824cdb843SMatthew G. Knepley }
192924cdb843SMatthew G. Knepley 
193011dd639bSMatthew G. Knepley static PetscErrorCode DMPlexComputeResidualFEM_Check_Internal(DM dm, Vec X, Vec X_t, PetscReal t, Vec F, void *user)
193124cdb843SMatthew G. Knepley {
193224cdb843SMatthew G. Knepley   DM                dmCh, dmAux;
1933c330f8ffSToby Isaac   Vec               A;
1934c330f8ffSToby Isaac   DMField           coordField = NULL;
193524cdb843SMatthew G. Knepley   PetscDS           prob, probCh, probAux = NULL;
193624cdb843SMatthew G. Knepley   PetscSection      section, sectionAux;
193724cdb843SMatthew G. Knepley   PetscScalar      *elemVec, *elemVecCh, *u, *u_t, *a = NULL;
1938c330f8ffSToby Isaac   PetscInt          Nf, f, numCells, cStart, cEnd, c;
19393755293bSMatthew G. Knepley   PetscInt          totDim, totDimAux = 0, diffCell = 0;
19404a3e9fdbSToby Isaac   PetscInt          depth;
1941c330f8ffSToby Isaac   PetscBool         isAffine;
1942c330f8ffSToby Isaac   IS                cellIS;
19434a3e9fdbSToby Isaac   DMLabel           depthLabel;
194424cdb843SMatthew G. Knepley   PetscErrorCode    ierr;
194524cdb843SMatthew G. Knepley 
194624cdb843SMatthew G. Knepley   PetscFunctionBegin;
194724cdb843SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
194824cdb843SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
194924cdb843SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
195024cdb843SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
195124cdb843SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
195224cdb843SMatthew G. Knepley   numCells = cEnd - cStart;
195324cdb843SMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "dmCh", (PetscObject *) &dmCh);CHKERRQ(ierr);
195424cdb843SMatthew G. Knepley   ierr = DMGetDS(dmCh, &probCh);CHKERRQ(ierr);
195524cdb843SMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr);
195624cdb843SMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr);
195724cdb843SMatthew G. Knepley   if (dmAux) {
195824cdb843SMatthew G. Knepley     ierr = DMGetDefaultSection(dmAux, &sectionAux);CHKERRQ(ierr);
195924cdb843SMatthew G. Knepley     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
196024cdb843SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
196124cdb843SMatthew G. Knepley   }
196224cdb843SMatthew G. Knepley   ierr = VecSet(F, 0.0);CHKERRQ(ierr);
1963bbce034cSMatthew G. Knepley   ierr = PetscMalloc3(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*totDim,&elemVec);CHKERRQ(ierr);
196424cdb843SMatthew G. Knepley   ierr = PetscMalloc1(numCells*totDim,&elemVecCh);CHKERRQ(ierr);
196524cdb843SMatthew G. Knepley   if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);}
19664a3e9fdbSToby Isaac   ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr);
19674a3e9fdbSToby Isaac   ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr);
19684a3e9fdbSToby Isaac   ierr = DMLabelGetStratumIS(depthLabel,depth,&cellIS);CHKERRQ(ierr);
19694a3e9fdbSToby Isaac   ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr);
197024cdb843SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
197124cdb843SMatthew G. Knepley     PetscScalar *x = NULL, *x_t = NULL;
197224cdb843SMatthew G. Knepley     PetscInt     i;
197324cdb843SMatthew G. Knepley 
197424cdb843SMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr);
197524cdb843SMatthew G. Knepley     for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i];
197624cdb843SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr);
197724cdb843SMatthew G. Knepley     if (X_t) {
197824cdb843SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr);
197924cdb843SMatthew G. Knepley       for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i];
198024cdb843SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr);
198124cdb843SMatthew G. Knepley     }
198224cdb843SMatthew G. Knepley     if (dmAux) {
19836da023fcSToby Isaac       DM dmAuxPlex;
19846da023fcSToby Isaac 
19856da023fcSToby Isaac       ierr = DMSNESConvertPlex(dmAux,&dmAuxPlex, PETSC_FALSE);CHKERRQ(ierr);
19866da023fcSToby Isaac       ierr = DMPlexVecGetClosure(dmAuxPlex, sectionAux, A, c, NULL, &x);CHKERRQ(ierr);
198724cdb843SMatthew G. Knepley       for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i];
19886da023fcSToby Isaac       ierr = DMPlexVecRestoreClosure(dmAuxPlex, sectionAux, A, c, NULL, &x);CHKERRQ(ierr);
19896da023fcSToby Isaac       ierr = DMDestroy(&dmAuxPlex);CHKERRQ(ierr);
199024cdb843SMatthew G. Knepley     }
199124cdb843SMatthew G. Knepley   }
199224cdb843SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
199324cdb843SMatthew G. Knepley     PetscFE  fe, feCh;
1994c330f8ffSToby Isaac     PetscInt Nq, Nb;
199524cdb843SMatthew G. Knepley     /* Conforming batches */
199624cdb843SMatthew G. Knepley     PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
199724cdb843SMatthew G. Knepley     /* Remainder */
199824cdb843SMatthew G. Knepley     PetscInt Nr, offset;
1999c330f8ffSToby Isaac     PetscQuadrature qGeom = NULL;
2000c330f8ffSToby Isaac     PetscFEGeom *cgeomFEM, *chunkGeom = NULL;
200124cdb843SMatthew G. Knepley 
200224cdb843SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr);
200324cdb843SMatthew G. Knepley     ierr = PetscDSGetDiscretization(probCh, f, (PetscObject *) &feCh);CHKERRQ(ierr);
200424cdb843SMatthew G. Knepley     ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
200524cdb843SMatthew G. Knepley     ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
2006c330f8ffSToby Isaac     ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr);
2007c330f8ffSToby Isaac     if (isAffine) {
2008c330f8ffSToby Isaac       ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr);
2009c330f8ffSToby Isaac     }
2010c330f8ffSToby Isaac     if (!qGeom) {
2011c330f8ffSToby Isaac       ierr = PetscFEGetQuadrature(fe, &qGeom);CHKERRQ(ierr);
2012c330f8ffSToby Isaac       ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr);
2013c330f8ffSToby Isaac     }
2014c330f8ffSToby Isaac     ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
20154a3e9fdbSToby Isaac     ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
2016c330f8ffSToby Isaac     blockSize = Nb;
201724cdb843SMatthew G. Knepley     batchSize = numBlocks * blockSize;
201824cdb843SMatthew G. Knepley     ierr =  PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
201924cdb843SMatthew G. Knepley     numChunks = numCells / (numBatches*batchSize);
202024cdb843SMatthew G. Knepley     Ne        = numChunks*numBatches*batchSize;
202124cdb843SMatthew G. Knepley     Nr        = numCells % (numBatches*batchSize);
202224cdb843SMatthew G. Knepley     offset    = numCells - Nr;
2023c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr);
2024c330f8ffSToby Isaac     ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec);CHKERRQ(ierr);
2025c330f8ffSToby Isaac     ierr = PetscFEIntegrateResidual(feCh, prob, f, Ne, chunkGeom, u, u_t, probAux, a, t, elemVecCh);CHKERRQ(ierr);
2026c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&chunkGeom);CHKERRQ(ierr);
2027c330f8ffSToby Isaac     ierr = PetscFEIntegrateResidual(fe, prob, f, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, &elemVec[offset*totDim]);CHKERRQ(ierr);
2028c330f8ffSToby Isaac     ierr = PetscFEIntegrateResidual(feCh, prob, f, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, &elemVecCh[offset*totDim]);CHKERRQ(ierr);
2029c330f8ffSToby Isaac     ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&chunkGeom);CHKERRQ(ierr);
20304a3e9fdbSToby Isaac     ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
2031c330f8ffSToby Isaac     ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr);
203224cdb843SMatthew G. Knepley   }
2033c330f8ffSToby Isaac   ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
203424cdb843SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
203524cdb843SMatthew G. Knepley     PetscBool diff = PETSC_FALSE;
203624cdb843SMatthew G. Knepley     PetscInt  d;
203724cdb843SMatthew G. Knepley 
203824cdb843SMatthew G. Knepley     for (d = 0; d < totDim; ++d) if (PetscAbsScalar(elemVec[c*totDim+d] - elemVecCh[c*totDim+d]) > 1.0e-7) {diff = PETSC_TRUE;break;}
203924cdb843SMatthew G. Knepley     if (diff) {
204024cdb843SMatthew G. Knepley       ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Different cell %d\n", c);CHKERRQ(ierr);
204124cdb843SMatthew G. Knepley       ierr = DMPrintCellVector(c, "Residual", totDim, &elemVec[c*totDim]);CHKERRQ(ierr);
204224cdb843SMatthew G. Knepley       ierr = DMPrintCellVector(c, "Check Residual", totDim, &elemVecCh[c*totDim]);CHKERRQ(ierr);
204324cdb843SMatthew G. Knepley       ++diffCell;
204424cdb843SMatthew G. Knepley     }
204524cdb843SMatthew G. Knepley     if (diffCell > 9) break;
2046c14a31d2SToby Isaac     ierr = DMPlexVecSetClosure(dm, section, F, c, &elemVec[c*totDim], ADD_ALL_VALUES);CHKERRQ(ierr);
204724cdb843SMatthew G. Knepley   }
2048bbce034cSMatthew G. Knepley   ierr = PetscFree3(u,u_t,elemVec);CHKERRQ(ierr);
204924cdb843SMatthew G. Knepley   ierr = PetscFree(elemVecCh);CHKERRQ(ierr);
205024cdb843SMatthew G. Knepley   if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);}
205124cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
205224cdb843SMatthew G. Knepley }
205324cdb843SMatthew G. Knepley 
205424cdb843SMatthew G. Knepley /*@
205524cdb843SMatthew G. Knepley   DMPlexSNESComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user
205624cdb843SMatthew G. Knepley 
205724cdb843SMatthew G. Knepley   Input Parameters:
205824cdb843SMatthew G. Knepley + dm - The mesh
205924cdb843SMatthew G. Knepley . X  - Local solution
206024cdb843SMatthew G. Knepley - user - The user context
206124cdb843SMatthew G. Knepley 
206224cdb843SMatthew G. Knepley   Output Parameter:
206324cdb843SMatthew G. Knepley . F  - Local output vector
206424cdb843SMatthew G. Knepley 
206524cdb843SMatthew G. Knepley   Level: developer
206624cdb843SMatthew G. Knepley 
206724cdb843SMatthew G. Knepley .seealso: DMPlexComputeJacobianActionFEM()
206824cdb843SMatthew G. Knepley @*/
206924cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user)
207024cdb843SMatthew G. Knepley {
207124cdb843SMatthew G. Knepley   PetscObject    check;
20726da023fcSToby Isaac   DM             plex;
20734a3e9fdbSToby Isaac   IS             cellIS;
20744a3e9fdbSToby Isaac   PetscInt       depth;
207524cdb843SMatthew G. Knepley   PetscErrorCode ierr;
207624cdb843SMatthew G. Knepley 
207724cdb843SMatthew G. Knepley   PetscFunctionBegin;
20786da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
20794a3e9fdbSToby Isaac   ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
2080aeadca18SToby Isaac   ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr);
20814a3e9fdbSToby Isaac   if (!cellIS) {
20824a3e9fdbSToby Isaac     ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr);
20834a3e9fdbSToby Isaac   }
208424cdb843SMatthew G. Knepley   /* The dmCh is used to check two mathematically equivalent discretizations for computational equivalence */
20856da023fcSToby Isaac   ierr = PetscObjectQuery((PetscObject) plex, "dmCh", &check);CHKERRQ(ierr);
208611dd639bSMatthew G. Knepley   if (check) {ierr = DMPlexComputeResidualFEM_Check_Internal(plex, X, NULL, 0.0, F, user);CHKERRQ(ierr);}
20874a3e9fdbSToby Isaac   else       {ierr = DMPlexComputeResidual_Internal(plex, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);}
20884a3e9fdbSToby Isaac   ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
20899a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
209024cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
209124cdb843SMatthew G. Knepley }
209224cdb843SMatthew G. Knepley 
2093bdd6f66aSToby Isaac /*@
2094bdd6f66aSToby Isaac   DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X
2095bdd6f66aSToby Isaac 
2096bdd6f66aSToby Isaac   Input Parameters:
2097bdd6f66aSToby Isaac + dm - The mesh
2098bdd6f66aSToby Isaac - user - The user context
2099bdd6f66aSToby Isaac 
2100bdd6f66aSToby Isaac   Output Parameter:
2101bdd6f66aSToby Isaac . X  - Local solution
2102bdd6f66aSToby Isaac 
2103bdd6f66aSToby Isaac   Level: developer
2104bdd6f66aSToby Isaac 
2105bdd6f66aSToby Isaac .seealso: DMPlexComputeJacobianActionFEM()
2106bdd6f66aSToby Isaac @*/
2107bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user)
2108bdd6f66aSToby Isaac {
2109bdd6f66aSToby Isaac   DM             plex;
2110bdd6f66aSToby Isaac   PetscErrorCode ierr;
2111bdd6f66aSToby Isaac 
2112bdd6f66aSToby Isaac   PetscFunctionBegin;
2113bdd6f66aSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
2114bdd6f66aSToby Isaac   ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr);
2115bdd6f66aSToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
2116bdd6f66aSToby Isaac   PetscFunctionReturn(0);
2117bdd6f66aSToby Isaac }
2118bdd6f66aSToby Isaac 
2119089bfe53SSander Arens PetscErrorCode DMPlexComputeBdJacobian_Internal(DM dm, Vec locX, Vec locX_t, PetscReal t, PetscReal X_tShift, Mat Jac, Mat JacP, void *user)
2120089bfe53SSander Arens {
2121089bfe53SSander Arens   DM_Plex         *mesh = (DM_Plex *) dm->data;
21222d91c981SSander Arens   DM               dmAux = NULL, plex = NULL;
2123c330f8ffSToby Isaac   DMField          coordField = NULL;
21242d91c981SSander Arens   PetscSection     section, globalSection, subSection, sectionAux = NULL;
21252d91c981SSander Arens   PetscDS          prob, probAux = NULL;
2126089bfe53SSander Arens   DMLabel          depth;
21272d91c981SSander Arens   Vec              locA = NULL;
21282d91c981SSander Arens   PetscScalar     *u = NULL, *u_t = NULL, *a = NULL, *elemMat = NULL;
21294d0b9603SSander Arens   PetscInt         dim, totDim, totDimAux, numBd, bd, Nf;
2130089bfe53SSander Arens   PetscBool        isMatISP;
2131c330f8ffSToby Isaac   IS               facetIS;
2132089bfe53SSander Arens   PetscErrorCode   ierr;
2133089bfe53SSander Arens 
2134089bfe53SSander Arens   PetscFunctionBegin;
2135089bfe53SSander Arens   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
2136089bfe53SSander Arens   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
2137089bfe53SSander Arens   ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatISP);CHKERRQ(ierr);
2138089bfe53SSander Arens   ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);
2139089bfe53SSander Arens   if (isMatISP) {
2140089bfe53SSander Arens     ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr);
2141089bfe53SSander Arens   }
2142089bfe53SSander Arens   ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr);
2143c330f8ffSToby Isaac   ierr = DMLabelGetStratumIS(depth,dim-1,&facetIS);CHKERRQ(ierr);
2144089bfe53SSander Arens   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
2145089bfe53SSander Arens   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
21464d0b9603SSander Arens   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
2147089bfe53SSander Arens   ierr = PetscDSGetNumBoundary(prob, &numBd);CHKERRQ(ierr);
21482d91c981SSander Arens   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &locA);CHKERRQ(ierr);
21492d91c981SSander Arens   if (locA) {
21502d91c981SSander Arens     ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr);
21512d91c981SSander Arens     ierr = DMConvert(dmAux, DMPLEX, &plex);CHKERRQ(ierr);
21522d91c981SSander Arens     ierr = DMGetDefaultSection(plex, &sectionAux);CHKERRQ(ierr);
21532d91c981SSander Arens     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
21544d0b9603SSander Arens     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
21552d91c981SSander Arens   }
21564a3e9fdbSToby Isaac   ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr);
2157089bfe53SSander Arens   for (bd = 0; bd < numBd; ++bd) {
2158df1fddb2SMatthew G. Knepley     DMBoundaryConditionType type;
2159089bfe53SSander Arens     const char             *bdLabel;
2160089bfe53SSander Arens     DMLabel                 label;
2161089bfe53SSander Arens     IS                      pointIS;
2162089bfe53SSander Arens     const PetscInt         *points;
2163089bfe53SSander Arens     const PetscInt         *values;
2164c330f8ffSToby Isaac     PetscInt                fieldI, fieldJ, numValues, v, numFaces, face, Nq;
2165089bfe53SSander Arens     PetscObject             obj;
2166c330f8ffSToby Isaac     PetscBool               isAffine;
2167c330f8ffSToby Isaac     PetscFE                 fe;
2168089bfe53SSander Arens     PetscClassId            id;
2169089bfe53SSander Arens 
2170df1fddb2SMatthew G. Knepley     ierr = PetscDSGetBoundary(prob, bd, &type, NULL, &bdLabel, &fieldI, NULL, NULL, NULL, &numValues, &values, NULL);CHKERRQ(ierr);
21714d0b9603SSander Arens     ierr = PetscDSGetDiscretization(prob, fieldI, &obj);CHKERRQ(ierr);
2172089bfe53SSander Arens     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
2173df1fddb2SMatthew G. Knepley     if ((id != PETSCFE_CLASSID) || (type & DM_BC_ESSENTIAL)) continue;
2174c330f8ffSToby Isaac     fe   = (PetscFE) obj;
2175089bfe53SSander Arens     ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr);
2176089bfe53SSander Arens     for (v = 0; v < numValues; ++v) {
2177c330f8ffSToby Isaac       PetscQuadrature qGeom = NULL;
2178c330f8ffSToby Isaac       PetscFEGeom     *fgeom;
2179c330f8ffSToby Isaac 
2180089bfe53SSander Arens       ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr);
2181089bfe53SSander Arens       if (!pointIS) continue; /* No points with that id on this process */
2182c330f8ffSToby Isaac       {
2183c330f8ffSToby Isaac         IS isectIS;
2184c330f8ffSToby Isaac 
2185c330f8ffSToby Isaac         /* TODO: Special cases of ISIntersect where it is quick to check a prior if one is a superset of the other */
21864a3e9fdbSToby Isaac         ierr = ISIntersect_Caching(facetIS,pointIS,&isectIS);CHKERRQ(ierr);
2187c330f8ffSToby Isaac         ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
2188c330f8ffSToby Isaac         pointIS = isectIS;
2189089bfe53SSander Arens       }
2190c330f8ffSToby Isaac       ierr = ISGetLocalSize(pointIS, &numFaces);CHKERRQ(ierr);
2191c330f8ffSToby Isaac       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
2192f99c8401SToby Isaac       ierr = PetscMalloc3(numFaces*totDim,&u,locX_t ? numFaces*totDim : 0,&u_t,numFaces*totDim*totDim,&elemMat);CHKERRQ(ierr);
21934d0b9603SSander Arens       if (locA) {ierr = PetscMalloc1(numFaces*totDimAux,&a);CHKERRQ(ierr);}
2194c330f8ffSToby Isaac       ierr = DMFieldGetFEInvariance(coordField,pointIS,NULL,&isAffine,NULL);CHKERRQ(ierr);
2195c330f8ffSToby Isaac       if (isAffine) {
2196c330f8ffSToby Isaac         ierr = DMFieldCreateDefaultQuadrature(coordField,pointIS,&qGeom);CHKERRQ(ierr);
2197c330f8ffSToby Isaac       }
2198c330f8ffSToby Isaac       if (!qGeom) {
2199c330f8ffSToby Isaac         ierr = PetscFEGetFaceQuadrature(fe, &qGeom);CHKERRQ(ierr);
2200c330f8ffSToby Isaac         ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr);
2201c330f8ffSToby Isaac       }
2202c330f8ffSToby Isaac       ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
22034a3e9fdbSToby Isaac       ierr = DMSNESGetFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr);
2204c330f8ffSToby Isaac       for (face = 0; face < numFaces; ++face) {
2205c330f8ffSToby Isaac         const PetscInt point = points[face], *support, *cone;
2206089bfe53SSander Arens         PetscScalar   *x     = NULL;
22079bfb2fe4SJed Brown         PetscInt       i, coneSize, faceLoc;
2208089bfe53SSander Arens 
22094d0b9603SSander Arens         ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr);
22104d0b9603SSander Arens         ierr = DMPlexGetConeSize(dm, support[0], &coneSize);CHKERRQ(ierr);
22114d0b9603SSander Arens         ierr = DMPlexGetCone(dm, support[0], &cone);CHKERRQ(ierr);
22124d0b9603SSander Arens         for (faceLoc = 0; faceLoc < coneSize; ++faceLoc) if (cone[faceLoc] == point) break;
22134d0b9603SSander Arens         if (faceLoc == coneSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of support[0] %d", point, support[0]);
2214f99c8401SToby Isaac         fgeom->face[face][0] = faceLoc;
22154d0b9603SSander Arens         ierr = DMPlexVecGetClosure(dm, section, locX, support[0], NULL, &x);CHKERRQ(ierr);
22164d0b9603SSander Arens         for (i = 0; i < totDim; ++i) u[face*totDim+i] = x[i];
22174d0b9603SSander Arens         ierr = DMPlexVecRestoreClosure(dm, section, locX, support[0], NULL, &x);CHKERRQ(ierr);
2218089bfe53SSander Arens         if (locX_t) {
22194d0b9603SSander Arens           ierr = DMPlexVecGetClosure(dm, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr);
22204d0b9603SSander Arens           for (i = 0; i < totDim; ++i) u_t[face*totDim+i] = x[i];
22214d0b9603SSander Arens           ierr = DMPlexVecRestoreClosure(dm, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr);
2222089bfe53SSander Arens         }
22232d91c981SSander Arens         if (locA) {
22244d0b9603SSander Arens           ierr = DMPlexVecGetClosure(plex, sectionAux, locA, support[0], NULL, &x);CHKERRQ(ierr);
22254d0b9603SSander Arens           for (i = 0; i < totDimAux; ++i) a[face*totDimAux+i] = x[i];
22264d0b9603SSander Arens           ierr = DMPlexVecRestoreClosure(plex, sectionAux, locA, support[0], NULL, &x);CHKERRQ(ierr);
22272d91c981SSander Arens         }
2228089bfe53SSander Arens       }
22294d0b9603SSander Arens       ierr = PetscMemzero(elemMat, numFaces*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);
2230089bfe53SSander Arens       {
2231089bfe53SSander Arens         PetscFE         fe;
2232c330f8ffSToby Isaac         PetscInt        Nb;
2233089bfe53SSander Arens         /* Conforming batches */
2234089bfe53SSander Arens         PetscInt        numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
2235089bfe53SSander Arens         /* Remainder */
2236c330f8ffSToby Isaac         PetscFEGeom    *chunkGeom = NULL;
2237089bfe53SSander Arens         PetscInt        Nr, offset;
2238089bfe53SSander Arens 
22394d0b9603SSander Arens         ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
2240089bfe53SSander Arens         ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
2241089bfe53SSander Arens         ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
2242c330f8ffSToby Isaac         blockSize = Nb;
2243089bfe53SSander Arens         batchSize = numBlocks * blockSize;
2244089bfe53SSander Arens         ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
2245089bfe53SSander Arens         numChunks = numFaces / (numBatches*batchSize);
2246089bfe53SSander Arens         Ne        = numChunks*numBatches*batchSize;
2247089bfe53SSander Arens         Nr        = numFaces % (numBatches*batchSize);
2248089bfe53SSander Arens         offset    = numFaces - Nr;
2249c330f8ffSToby Isaac         ierr = PetscFEGeomGetChunk(fgeom,0,offset,&chunkGeom);CHKERRQ(ierr);
2250089bfe53SSander Arens         for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
2251c330f8ffSToby Isaac           ierr = PetscFEIntegrateBdJacobian(fe, prob, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr);
2252089bfe53SSander Arens         }
2253c330f8ffSToby Isaac         ierr = PetscFEGeomGetChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr);
2254c330f8ffSToby Isaac         for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
2255c330f8ffSToby Isaac           ierr = PetscFEIntegrateBdJacobian(fe, prob, fieldI, fieldJ, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, a ? &a[offset*totDimAux] : NULL, t, X_tShift, &elemMat[offset*totDim*totDim]);CHKERRQ(ierr);
2256089bfe53SSander Arens         }
2257c330f8ffSToby Isaac         ierr = PetscFEGeomRestoreChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr);
2258c330f8ffSToby Isaac       }
2259c330f8ffSToby Isaac       for (face = 0; face < numFaces; ++face) {
2260c330f8ffSToby Isaac         const PetscInt point = points[face], *support;
2261089bfe53SSander Arens 
22624d0b9603SSander Arens         if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(point, "BdJacobian", totDim, totDim, &elemMat[face*totDim*totDim]);CHKERRQ(ierr);}
22634d0b9603SSander Arens         ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr);
2264089bfe53SSander Arens         if (!isMatISP) {
22654d0b9603SSander Arens           ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, support[0], &elemMat[face*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2266089bfe53SSander Arens         } else {
2267089bfe53SSander Arens           Mat lJ;
2268089bfe53SSander Arens 
2269089bfe53SSander Arens           ierr = MatISGetLocalMat(JacP,&lJ);CHKERRQ(ierr);
22704d0b9603SSander Arens           ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, support[0], &elemMat[face*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2271089bfe53SSander Arens         }
2272089bfe53SSander Arens       }
22734a3e9fdbSToby Isaac       ierr = DMSNESRestoreFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr);
2274c330f8ffSToby Isaac       ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr);
2275f99c8401SToby Isaac       ierr = PetscFree3(u,u_t,elemMat);CHKERRQ(ierr);
2276089bfe53SSander Arens       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
2277089bfe53SSander Arens       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
22781c46aac1SSander Arens       if (locA) {ierr = PetscFree(a);CHKERRQ(ierr);}
22792d91c981SSander Arens     }
2280089bfe53SSander Arens   }
2281c330f8ffSToby Isaac   ierr = ISDestroy(&facetIS);CHKERRQ(ierr);
22821c46aac1SSander Arens   if (plex) {ierr = DMDestroy(&plex);CHKERRQ(ierr);}
2283089bfe53SSander Arens   PetscFunctionReturn(0);
2284089bfe53SSander Arens }
2285089bfe53SSander Arens 
2286f7e6ed9bSMatthew G. Knepley /*
2287f7e6ed9bSMatthew G. Knepley   We always assemble JacP, and if the matrix is different from Jac and two different sets of point functions are provided, we also assemble Jac
2288f7e6ed9bSMatthew G. Knepley 
2289f7e6ed9bSMatthew G. Knepley   X   - The local solution vector
2290f7e6ed9bSMatthew G. Knepley   X_t - The local solution time derviative vector, or NULL
2291f7e6ed9bSMatthew G. Knepley */
2292f7e6ed9bSMatthew G. Knepley PetscErrorCode DMPlexComputeJacobian_Patch_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscInt cStart, PetscInt cEnd, const PetscInt *cells,
2293f7e6ed9bSMatthew G. Knepley                                                     PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Mat Jac, Mat JacP, void *ctx)
2294f7e6ed9bSMatthew G. Knepley {
2295f7e6ed9bSMatthew G. Knepley   DM_Plex         *mesh  = (DM_Plex *) dm->data;
2296f7e6ed9bSMatthew G. Knepley   const char      *name = "Jacobian", *nameP = "JacobianPre";
2297f7e6ed9bSMatthew G. Knepley   DM               dmCell, dmAux = NULL;
2298f7e6ed9bSMatthew G. Knepley   PetscDS          prob,   probAux = NULL;
2299f7e6ed9bSMatthew G. Knepley   PetscSection     sectionAux = NULL;
2300f7e6ed9bSMatthew G. Knepley   Vec              cellgeom, A;
2301f7e6ed9bSMatthew G. Knepley   Mat              J = Jac, JP = JacP;
2302f7e6ed9bSMatthew G. Knepley   PetscScalar     *work, *u = NULL, *u_t = NULL, *a = NULL, *elemMat = NULL, *elemMatP = NULL, *elemMatD = NULL, *cgeomScal;
2303f7e6ed9bSMatthew G. Knepley   PetscFECellGeom *cgeomCon = NULL;
2304f7e6ed9bSMatthew G. Knepley   PetscBool        hasJac, hasPrec, hasDyn, assembleJac, isMatIS, isMatISP, extractGeom, *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE;
2305f7e6ed9bSMatthew G. Knepley   const PetscInt   numCells = cEnd-cStart;
2306f7e6ed9bSMatthew G. Knepley   PetscInt         Nf, fieldI, fieldJ, numChunks, chunkSize, chunk, totDim, totDimAux = 0, sz, wsz, off = 0, offCell = 0;
2307f7e6ed9bSMatthew G. Knepley   PetscErrorCode   ierr;
2308f7e6ed9bSMatthew G. Knepley 
2309f7e6ed9bSMatthew G. Knepley   PetscFunctionBegin;
2310f7e6ed9bSMatthew G. Knepley   CHKMEMQ;
2311f7e6ed9bSMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
2312f7e6ed9bSMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
2313f7e6ed9bSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr);
2314f7e6ed9bSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr);
2315f7e6ed9bSMatthew G. Knepley   if (dmAux) {
2316f7e6ed9bSMatthew G. Knepley     ierr = DMGetDefaultSection(dmAux, &sectionAux);CHKERRQ(ierr);
2317f7e6ed9bSMatthew G. Knepley     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
2318f7e6ed9bSMatthew G. Knepley   }
2319f7e6ed9bSMatthew G. Knepley   /* Get flags */
2320f7e6ed9bSMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
2321f7e6ed9bSMatthew G. Knepley   ierr = DMGetWorkArray(dm, Nf, MPIU_BOOL, &isFE);CHKERRQ(ierr);
2322f7e6ed9bSMatthew G. Knepley   for (fieldI = 0; fieldI < Nf; ++fieldI) {
2323f7e6ed9bSMatthew G. Knepley     PetscObject  disc;
2324f7e6ed9bSMatthew G. Knepley     PetscClassId id;
2325f7e6ed9bSMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, fieldI, &disc);CHKERRQ(ierr);
2326f7e6ed9bSMatthew G. Knepley     ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr);
2327f7e6ed9bSMatthew G. Knepley     if (id == PETSCFE_CLASSID)      {hasFE = PETSC_TRUE; isFE[fieldI] = PETSC_TRUE;}
2328f7e6ed9bSMatthew G. Knepley     else if (id == PETSCFV_CLASSID) {hasFV = PETSC_TRUE; isFE[fieldI] = PETSC_FALSE;}
2329f7e6ed9bSMatthew G. Knepley   }
2330f7e6ed9bSMatthew G. Knepley   ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr);
2331f7e6ed9bSMatthew G. Knepley   ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr);
2332f7e6ed9bSMatthew G. Knepley   ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr);
2333f7e6ed9bSMatthew G. Knepley   assembleJac = hasJac && hasPrec && (Jac != JacP) ? PETSC_TRUE : PETSC_FALSE;
2334f7e6ed9bSMatthew G. Knepley   hasDyn      = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
2335f7e6ed9bSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) Jac,  MATIS, &isMatIS);CHKERRQ(ierr);
2336f7e6ed9bSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatISP);CHKERRQ(ierr);
2337f7e6ed9bSMatthew G. Knepley   extractGeom = sizeof(PetscFECellGeom) % sizeof(PetscScalar) ? PETSC_TRUE : PETSC_FALSE;
2338f7e6ed9bSMatthew G. Knepley   /* Setup input data and temp arrays (should be DMGetWorkArray) */
2339f7e6ed9bSMatthew G. Knepley   if (isMatISP || isMatISP) {ierr = DMPlexGetSubdomainSection(dm, &globalSection);CHKERRQ(ierr);}
2340f7e6ed9bSMatthew G. Knepley   if (isMatIS)  {ierr = MatISGetLocalMat(Jac,  &J);CHKERRQ(ierr);}
2341f7e6ed9bSMatthew G. Knepley   if (isMatISP) {ierr = MatISGetLocalMat(JacP, &JP);CHKERRQ(ierr);}
2342f7e6ed9bSMatthew G. Knepley   if (hasFV)    {ierr = MatSetOption(JP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE);CHKERRQ(ierr);} /* No allocated space for FV stuff, so ignore the zero entries */
2343f7e6ed9bSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr);
2344f7e6ed9bSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr);
2345f7e6ed9bSMatthew G. Knepley   ierr = DMPlexSNESGetGeometryFEM(dm, &cellgeom);CHKERRQ(ierr);
2346f7e6ed9bSMatthew G. Knepley   ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr);
2347f7e6ed9bSMatthew G. Knepley   ierr = VecGetArray(cellgeom, &cgeomScal);CHKERRQ(ierr);
2348f7e6ed9bSMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
2349f7e6ed9bSMatthew G. Knepley   if (probAux) {ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);}
2350f7e6ed9bSMatthew G. Knepley   CHKMEMQ;
2351f7e6ed9bSMatthew G. Knepley   /* Compute batch sizes */
2352f7e6ed9bSMatthew G. Knepley   if (isFE[0]) {
2353f7e6ed9bSMatthew G. Knepley     PetscFE         fe;
2354f7e6ed9bSMatthew G. Knepley     PetscQuadrature q;
2355f7e6ed9bSMatthew G. Knepley     PetscInt        numQuadPoints, numBatches, batchSize, numBlocks, blockSize, Nb;
2356f7e6ed9bSMatthew G. Knepley 
2357f7e6ed9bSMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr);
2358f7e6ed9bSMatthew G. Knepley     ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
2359f7e6ed9bSMatthew G. Knepley     ierr = PetscQuadratureGetData(q, NULL, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr);
2360f7e6ed9bSMatthew G. Knepley     ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
2361f7e6ed9bSMatthew G. Knepley     ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
2362f7e6ed9bSMatthew G. Knepley     blockSize = Nb*numQuadPoints;
2363f7e6ed9bSMatthew G. Knepley     batchSize = numBlocks  * blockSize;
2364f7e6ed9bSMatthew G. Knepley     chunkSize = numBatches * batchSize;
2365f7e6ed9bSMatthew G. Knepley     numChunks = numCells / chunkSize + numCells % chunkSize;
2366f7e6ed9bSMatthew G. Knepley     ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
2367f7e6ed9bSMatthew G. Knepley   } else {
2368f7e6ed9bSMatthew G. Knepley     chunkSize = numCells;
2369f7e6ed9bSMatthew G. Knepley     numChunks = 1;
2370f7e6ed9bSMatthew G. Knepley   }
2371f7e6ed9bSMatthew G. Knepley   /* Get work space */
2372f7e6ed9bSMatthew G. Knepley   if (extractGeom) {ierr = PetscMalloc1(chunkSize, &cgeomCon);CHKERRQ(ierr);}
2373f7e6ed9bSMatthew G. Knepley   wsz  = (((X?1:0) + (X_t?1:0) + (dmAux?1:0))*totDim + ((hasJac?1:0) + (hasPrec?1:0) + (hasDyn?1:0))*totDim*totDim)*chunkSize;
2374f7e6ed9bSMatthew G. Knepley   ierr = DMGetWorkArray(dm, wsz, MPIU_SCALAR, &work);CHKERRQ(ierr);
2375f7e6ed9bSMatthew G. Knepley   ierr = PetscMemzero(work, wsz * sizeof(PetscScalar));CHKERRQ(ierr);
2376f7e6ed9bSMatthew G. Knepley   off      = 0;
2377f7e6ed9bSMatthew G. Knepley   u        = X       ? (sz = chunkSize*totDim,        off += sz, work+off-sz) : NULL;
2378f7e6ed9bSMatthew G. Knepley   u_t      = X_t     ? (sz = chunkSize*totDim,        off += sz, work+off-sz) : NULL;
2379f7e6ed9bSMatthew G. Knepley   a        = dmAux   ? (sz = chunkSize*totDimAux,     off += sz, work+off-sz) : NULL;
2380f7e6ed9bSMatthew G. Knepley   elemMat  = hasJac  ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL;
2381f7e6ed9bSMatthew G. Knepley   elemMatP = hasPrec ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL;
2382f7e6ed9bSMatthew G. Knepley   elemMatD = hasDyn  ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL;
2383f7e6ed9bSMatthew G. Knepley   if (off != wsz) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error is workspace size %D should be %D", off, wsz);
2384f7e6ed9bSMatthew G. Knepley   /* Compute volume integrals */
2385f7e6ed9bSMatthew G. Knepley   if (assembleJac) {ierr = MatZeroEntries(J);CHKERRQ(ierr);}
2386f7e6ed9bSMatthew G. Knepley   ierr = MatZeroEntries(JP);CHKERRQ(ierr);
2387f7e6ed9bSMatthew G. Knepley   for (chunk = 0; chunk < numChunks; ++chunk, offCell += chunkSize) {
2388f7e6ed9bSMatthew G. Knepley     const PetscInt   Ncell = PetscMin(chunkSize, numCells - offCell);
2389f7e6ed9bSMatthew G. Knepley     PetscFECellGeom *cgeom = extractGeom ? cgeomCon : &(((PetscFECellGeom *) cgeomScal)[offCell]);
2390f7e6ed9bSMatthew G. Knepley     PetscInt         c;
2391f7e6ed9bSMatthew G. Knepley 
2392f7e6ed9bSMatthew G. Knepley     /* Extract values */
2393f7e6ed9bSMatthew G. Knepley     for (c = 0; c < Ncell; ++c) {
2394f7e6ed9bSMatthew G. Knepley       const PetscInt cell = cells ? cells[c+offCell] : c+offCell;
2395f7e6ed9bSMatthew G. Knepley       PetscScalar   *x = NULL,  *x_t = NULL;
2396f7e6ed9bSMatthew G. Knepley       PetscInt       i;
2397f7e6ed9bSMatthew G. Knepley 
2398f7e6ed9bSMatthew G. Knepley       if (X) {
2399f7e6ed9bSMatthew G. Knepley         ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
2400f7e6ed9bSMatthew G. Knepley         for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i];
2401f7e6ed9bSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
2402f7e6ed9bSMatthew G. Knepley       }
2403f7e6ed9bSMatthew G. Knepley       if (X_t) {
2404f7e6ed9bSMatthew G. Knepley         ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
2405f7e6ed9bSMatthew G. Knepley         for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i];
2406f7e6ed9bSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
2407f7e6ed9bSMatthew G. Knepley       }
2408f7e6ed9bSMatthew G. Knepley       if (dmAux) {
2409f7e6ed9bSMatthew G. Knepley         ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr);
2410f7e6ed9bSMatthew G. Knepley         for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i];
2411f7e6ed9bSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr);
2412f7e6ed9bSMatthew G. Knepley       }
2413f7e6ed9bSMatthew G. Knepley       if (extractGeom) {
2414f7e6ed9bSMatthew G. Knepley         ierr = DMPlexPointLocalRef(dmCell, cell, cgeomScal, &x);CHKERRQ(ierr);
2415f7e6ed9bSMatthew G. Knepley         cgeomCon[c] = *((PetscFECellGeom *) x);
2416f7e6ed9bSMatthew G. Knepley       }
2417f7e6ed9bSMatthew G. Knepley     }
2418f7e6ed9bSMatthew G. Knepley     CHKMEMQ;
2419f7e6ed9bSMatthew G. Knepley     for (fieldI = 0; fieldI < Nf; ++fieldI) {
2420f7e6ed9bSMatthew G. Knepley       PetscFE fe;
2421f7e6ed9bSMatthew G. Knepley       ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
2422f7e6ed9bSMatthew G. Knepley       for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
2423f7e6ed9bSMatthew G. Knepley         if (hasJac)  {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN,     fieldI, fieldJ, Ncell, cgeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr);}
2424f7e6ed9bSMatthew G. Knepley         if (hasPrec) {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_PRE, fieldI, fieldJ, Ncell, cgeom, u, u_t, probAux, a, t, X_tShift, elemMatP);CHKERRQ(ierr);}
2425f7e6ed9bSMatthew G. Knepley         if (hasDyn)  {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Ncell, cgeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr);}
2426f7e6ed9bSMatthew G. Knepley       }
2427f7e6ed9bSMatthew G. Knepley       /* For finite volume, add the identity */
2428f7e6ed9bSMatthew G. Knepley       if (!isFE[fieldI]) {
2429f7e6ed9bSMatthew G. Knepley         PetscFV  fv;
2430f7e6ed9bSMatthew G. Knepley         PetscInt eOffset = 0, Nc, fc, foff;
2431f7e6ed9bSMatthew G. Knepley 
2432f7e6ed9bSMatthew G. Knepley         ierr = PetscDSGetFieldOffset(prob, fieldI, &foff);CHKERRQ(ierr);
2433f7e6ed9bSMatthew G. Knepley         ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fv);CHKERRQ(ierr);
2434f7e6ed9bSMatthew G. Knepley         ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr);
2435f7e6ed9bSMatthew G. Knepley         for (c = 0; c < chunkSize; ++c, eOffset += totDim*totDim) {
2436f7e6ed9bSMatthew G. Knepley           for (fc = 0; fc < Nc; ++fc) {
2437f7e6ed9bSMatthew G. Knepley             const PetscInt i = foff + fc;
2438f7e6ed9bSMatthew G. Knepley             if (hasJac)  {elemMat [eOffset+i*totDim+i] = 1.0;}
2439f7e6ed9bSMatthew G. Knepley             if (hasPrec) {elemMatP[eOffset+i*totDim+i] = 1.0;}
2440f7e6ed9bSMatthew G. Knepley           }
2441f7e6ed9bSMatthew G. Knepley         }
2442f7e6ed9bSMatthew G. Knepley       }
2443f7e6ed9bSMatthew G. Knepley     }
2444f7e6ed9bSMatthew G. Knepley     CHKMEMQ;
2445f7e6ed9bSMatthew G. Knepley     /*   Add contribution from X_t */
2446f7e6ed9bSMatthew G. Knepley     if (hasDyn) {for (c = 0; c < chunkSize*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c];}
2447f7e6ed9bSMatthew G. Knepley     /* Insert values into matrix */
2448f7e6ed9bSMatthew G. Knepley     for (c = 0; c < Ncell; ++c) {
2449f7e6ed9bSMatthew G. Knepley       const PetscInt cell = cells ? cells[c+offCell] : c+offCell;
2450f7e6ed9bSMatthew G. Knepley       if (mesh->printFEM > 1) {
2451f7e6ed9bSMatthew G. Knepley         if (hasJac)  {ierr = DMPrintCellMatrix(cell, name,  totDim, totDim, &elemMat[(c-cStart)*totDim*totDim]);CHKERRQ(ierr);}
2452f7e6ed9bSMatthew G. Knepley         if (hasPrec) {ierr = DMPrintCellMatrix(cell, nameP, totDim, totDim, &elemMatP[(c-cStart)*totDim*totDim]);CHKERRQ(ierr);}
2453f7e6ed9bSMatthew G. Knepley       }
2454f7e6ed9bSMatthew G. Knepley       if (assembleJac) {ierr = DMPlexMatSetClosure(dm, section, globalSection, Jac, cell, &elemMat[(c-cStart)*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);}
2455f7e6ed9bSMatthew G. Knepley       ierr = DMPlexMatSetClosure(dm, section, globalSection, JP, cell, &elemMat[(c-cStart)*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2456f7e6ed9bSMatthew G. Knepley     }
2457f7e6ed9bSMatthew G. Knepley     CHKMEMQ;
2458f7e6ed9bSMatthew G. Knepley   }
2459f7e6ed9bSMatthew G. Knepley   /* Cleanup */
2460f7e6ed9bSMatthew G. Knepley   if (hasFV) {ierr = MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE);CHKERRQ(ierr);}
2461f7e6ed9bSMatthew G. Knepley   ierr = VecRestoreArray(cellgeom, &cgeomScal);CHKERRQ(ierr);
2462f7e6ed9bSMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, Nf, PETSC_BOOL, &isFE);CHKERRQ(ierr);
2463f7e6ed9bSMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, ((1 + (X_t?1:0) + (dmAux?1:0))*totDim + ((hasJac?1:0) + (hasPrec?1:0) + (hasDyn?1:0))*totDim*totDim)*chunkSize, PETSC_SCALAR, &work);CHKERRQ(ierr);
2464f7e6ed9bSMatthew G. Knepley   if (extractGeom) {ierr = PetscFree(cgeomCon);CHKERRQ(ierr);}
2465f7e6ed9bSMatthew G. Knepley   /* Compute boundary integrals */
2466*2cf2a403SMatthew G. Knepley   /* ierr = DMPlexComputeBdJacobian_Internal(dm, X, X_t, t, X_tShift, Jac, JacP, ctx);CHKERRQ(ierr); */
2467f7e6ed9bSMatthew G. Knepley   /* Assemble matrix */
2468f7e6ed9bSMatthew G. Knepley   if (assembleJac) {ierr = MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);ierr = MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);}
2469f7e6ed9bSMatthew G. Knepley   ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2470f7e6ed9bSMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
2471f7e6ed9bSMatthew G. Knepley   CHKMEMQ;
2472f7e6ed9bSMatthew G. Knepley   PetscFunctionReturn(0);
2473f7e6ed9bSMatthew G. Knepley }
2474f7e6ed9bSMatthew G. Knepley 
24754a3e9fdbSToby Isaac PetscErrorCode DMPlexComputeJacobian_Internal(DM dm, IS cellIS, PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Mat Jac, Mat JacP,void *user)
247624cdb843SMatthew G. Knepley {
247724cdb843SMatthew G. Knepley   DM_Plex        *mesh  = (DM_Plex *) dm->data;
247824cdb843SMatthew G. Knepley   const char     *name  = "Jacobian";
2479f7ed7b21SMatthew G. Knepley   DM              dmAux, plex;
2480c330f8ffSToby Isaac   Vec             A;
2481c330f8ffSToby Isaac   DMField         coordField;
248224cdb843SMatthew G. Knepley   PetscDS         prob, probAux = NULL;
2483be36d101SStefano Zampini   PetscSection    section, globalSection, subSection, sectionAux;
2484426ff135SMatthew G. Knepley   PetscScalar    *elemMat, *elemMatP, *elemMatD, *u, *u_t, *a = NULL;
24859044fa66SMatthew G. Knepley   const PetscInt *cells;
24869044fa66SMatthew G. Knepley   PetscInt        Nf, fieldI, fieldJ;
24879044fa66SMatthew G. Knepley   PetscInt        totDim, totDimAux, cStart, cEnd, numCells, c;
2488be36d101SStefano Zampini   PetscBool       isMatIS, isMatISP, isShell, hasJac, hasPrec, hasDyn, hasFV = PETSC_FALSE;
248924cdb843SMatthew G. Knepley   PetscErrorCode  ierr;
249024cdb843SMatthew G. Knepley 
249124cdb843SMatthew G. Knepley   PetscFunctionBegin;
249224cdb843SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
249324cdb843SMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
2494be36d101SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatISP);CHKERRQ(ierr);
249524cdb843SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);
24965bf53532SMatthew G. Knepley   if (isMatISP) {ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr);}
249724cdb843SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
249824cdb843SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
2499efc10488SMatthew G. Knepley   ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr);
250055ad3c34SMatthew G. Knepley   ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr);
2501426ff135SMatthew G. Knepley   ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr);
2502426ff135SMatthew G. Knepley   hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
250324cdb843SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
25044a3e9fdbSToby Isaac   ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr);
25059044fa66SMatthew G. Knepley   ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
250624cdb843SMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr);
250724cdb843SMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr);
250824cdb843SMatthew G. Knepley   if (dmAux) {
2509f7ed7b21SMatthew G. Knepley     ierr = DMConvert(dmAux, DMPLEX, &plex);CHKERRQ(ierr);
2510f7ed7b21SMatthew G. Knepley     ierr = DMGetDefaultSection(plex, &sectionAux);CHKERRQ(ierr);
251124cdb843SMatthew G. Knepley     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
251224cdb843SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
251324cdb843SMatthew G. Knepley   }
2514efc10488SMatthew G. Knepley   ierr = PetscMalloc5(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,hasJac ? numCells*totDim*totDim : 0,&elemMat,hasPrec ? numCells*totDim*totDim : 0, &elemMatP,hasDyn ? numCells*totDim*totDim : 0, &elemMatD);CHKERRQ(ierr);
251524cdb843SMatthew G. Knepley   if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);}
25164a3e9fdbSToby Isaac   ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr);
251724cdb843SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
25189044fa66SMatthew G. Knepley     const PetscInt cell = cells ? cells[c] : c;
25199044fa66SMatthew G. Knepley     const PetscInt cind = c - cStart;
252024cdb843SMatthew G. Knepley     PetscScalar   *x = NULL,  *x_t = NULL;
252124cdb843SMatthew G. Knepley     PetscInt       i;
252224cdb843SMatthew G. Knepley 
25239044fa66SMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
25249044fa66SMatthew G. Knepley     for (i = 0; i < totDim; ++i) u[cind*totDim+i] = x[i];
25259044fa66SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
252624cdb843SMatthew G. Knepley     if (X_t) {
25279044fa66SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
25289044fa66SMatthew G. Knepley       for (i = 0; i < totDim; ++i) u_t[cind*totDim+i] = x_t[i];
25299044fa66SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
253024cdb843SMatthew G. Knepley     }
253124cdb843SMatthew G. Knepley     if (dmAux) {
25329044fa66SMatthew G. Knepley       ierr = DMPlexVecGetClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr);
25339044fa66SMatthew G. Knepley       for (i = 0; i < totDimAux; ++i) a[cind*totDimAux+i] = x[i];
25349044fa66SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr);
253524cdb843SMatthew G. Knepley     }
253624cdb843SMatthew G. Knepley   }
2537efc10488SMatthew G. Knepley   if (hasJac)  {ierr = PetscMemzero(elemMat,  numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);}
253855ad3c34SMatthew G. Knepley   if (hasPrec) {ierr = PetscMemzero(elemMatP, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);}
2539426ff135SMatthew G. Knepley   if (hasDyn)  {ierr = PetscMemzero(elemMatD, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);}
254024cdb843SMatthew G. Knepley   for (fieldI = 0; fieldI < Nf; ++fieldI) {
25415244db28SMatthew G. Knepley     PetscClassId    id;
254224cdb843SMatthew G. Knepley     PetscFE         fe;
2543c330f8ffSToby Isaac     PetscQuadrature qGeom = NULL;
2544c330f8ffSToby Isaac     PetscInt        Nb;
254524cdb843SMatthew G. Knepley     /* Conforming batches */
254624cdb843SMatthew G. Knepley     PetscInt        numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
254724cdb843SMatthew G. Knepley     /* Remainder */
2548c330f8ffSToby Isaac     PetscInt        Nr, offset, Nq;
2549c330f8ffSToby Isaac     PetscBool       isAffine;
2550c330f8ffSToby Isaac     PetscFEGeom     *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL;
255124cdb843SMatthew G. Knepley 
255224cdb843SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
25535244db28SMatthew G. Knepley     ierr = PetscObjectGetClassId((PetscObject) fe, &id);CHKERRQ(ierr);
25545244db28SMatthew G. Knepley     if (id == PETSCFV_CLASSID) {hasFV = PETSC_TRUE; continue;}
255524cdb843SMatthew G. Knepley     ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
255624cdb843SMatthew G. Knepley     ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
2557c330f8ffSToby Isaac     ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr);
2558c330f8ffSToby Isaac     if (isAffine) {
2559c330f8ffSToby Isaac       ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr);
2560c330f8ffSToby Isaac     }
2561c330f8ffSToby Isaac     if (!qGeom) {
2562c330f8ffSToby Isaac       ierr = PetscFEGetQuadrature(fe,&qGeom);CHKERRQ(ierr);
2563c330f8ffSToby Isaac       ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr);
2564c330f8ffSToby Isaac     }
2565c330f8ffSToby Isaac     ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
25664a3e9fdbSToby Isaac     ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
2567c330f8ffSToby Isaac     blockSize = Nb;
256824cdb843SMatthew G. Knepley     batchSize = numBlocks * blockSize;
256924cdb843SMatthew G. Knepley     ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
257024cdb843SMatthew G. Knepley     numChunks = numCells / (numBatches*batchSize);
257124cdb843SMatthew G. Knepley     Ne        = numChunks*numBatches*batchSize;
257224cdb843SMatthew G. Knepley     Nr        = numCells % (numBatches*batchSize);
257324cdb843SMatthew G. Knepley     offset    = numCells - Nr;
2574c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr);
2575c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr);
257624cdb843SMatthew G. Knepley     for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
2577efc10488SMatthew G. Knepley       if (hasJac) {
2578c330f8ffSToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr);
2579c330f8ffSToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMat[offset*totDim*totDim]);CHKERRQ(ierr);
2580efc10488SMatthew G. Knepley       }
258155ad3c34SMatthew G. Knepley       if (hasPrec) {
2582c330f8ffSToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_PRE, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatP);CHKERRQ(ierr);
2583c330f8ffSToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_PRE, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMatP[offset*totDim*totDim]);CHKERRQ(ierr);
2584426ff135SMatthew G. Knepley       }
2585426ff135SMatthew G. Knepley       if (hasDyn) {
2586c330f8ffSToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr);
2587c330f8ffSToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMatD[offset*totDim*totDim]);CHKERRQ(ierr);
258855ad3c34SMatthew G. Knepley       }
258924cdb843SMatthew G. Knepley     }
2590c330f8ffSToby Isaac     ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr);
2591c330f8ffSToby Isaac     ierr = PetscFEGeomRestoreChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr);
25924a3e9fdbSToby Isaac     ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
2593c330f8ffSToby Isaac     ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr);
259424cdb843SMatthew G. Knepley   }
25955bf53532SMatthew G. Knepley   /*   Add contribution from X_t */
25969044fa66SMatthew G. Knepley   if (hasDyn) {for (c = 0; c < numCells*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c];}
25975244db28SMatthew G. Knepley   if (hasFV) {
25985244db28SMatthew G. Knepley     PetscClassId id;
25995244db28SMatthew G. Knepley     PetscFV      fv;
26005244db28SMatthew G. Knepley     PetscInt     offsetI, NcI, NbI = 1, fc, f;
26015244db28SMatthew G. Knepley 
26025244db28SMatthew G. Knepley     for (fieldI = 0; fieldI < Nf; ++fieldI) {
26035244db28SMatthew G. Knepley       ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fv);CHKERRQ(ierr);
26045244db28SMatthew G. Knepley       ierr = PetscDSGetFieldOffset(prob, fieldI, &offsetI);CHKERRQ(ierr);
26055244db28SMatthew G. Knepley       ierr = PetscObjectGetClassId((PetscObject) fv, &id);CHKERRQ(ierr);
26065244db28SMatthew G. Knepley       if (id != PETSCFV_CLASSID) continue;
26075244db28SMatthew G. Knepley       /* Put in the identity */
26085244db28SMatthew G. Knepley       ierr = PetscFVGetNumComponents(fv, &NcI);CHKERRQ(ierr);
26095244db28SMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
26109044fa66SMatthew G. Knepley         const PetscInt cind    = c - cStart;
26119044fa66SMatthew G. Knepley         const PetscInt eOffset = cind*totDim*totDim;
26125244db28SMatthew G. Knepley         for (fc = 0; fc < NcI; ++fc) {
26135244db28SMatthew G. Knepley           for (f = 0; f < NbI; ++f) {
26145244db28SMatthew G. Knepley             const PetscInt i = offsetI + f*NcI+fc;
26155244db28SMatthew G. Knepley             if (hasPrec) {
26165244db28SMatthew G. Knepley               if (hasJac) {elemMat[eOffset+i*totDim+i] = 1.0;}
26175244db28SMatthew G. Knepley               elemMatP[eOffset+i*totDim+i] = 1.0;
26185244db28SMatthew G. Knepley             } else {elemMat[eOffset+i*totDim+i] = 1.0;}
26195244db28SMatthew G. Knepley           }
26205244db28SMatthew G. Knepley         }
26215244db28SMatthew G. Knepley       }
26225244db28SMatthew G. Knepley     }
26235244db28SMatthew G. Knepley     /* No allocated space for FV stuff, so ignore the zero entries */
26245244db28SMatthew G. Knepley     ierr = MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE);CHKERRQ(ierr);
26255244db28SMatthew G. Knepley   }
26265bf53532SMatthew G. Knepley   /* Insert values into matrix */
2627be36d101SStefano Zampini   isMatIS = PETSC_FALSE;
2628be36d101SStefano Zampini   if (hasPrec && hasJac) {
2629be36d101SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatIS);CHKERRQ(ierr);
2630be36d101SStefano Zampini   }
2631be36d101SStefano Zampini   if (isMatIS && !subSection) {
2632be36d101SStefano Zampini     ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr);
2633be36d101SStefano Zampini   }
263424cdb843SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
26359044fa66SMatthew G. Knepley     const PetscInt cell = cells ? cells[c] : c;
26369044fa66SMatthew G. Knepley     const PetscInt cind = c - cStart;
26379044fa66SMatthew G. Knepley 
263855ad3c34SMatthew G. Knepley     if (hasPrec) {
2639efc10488SMatthew G. Knepley       if (hasJac) {
26409044fa66SMatthew G. Knepley         if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr);}
2641be36d101SStefano Zampini         if (!isMatIS) {
26429044fa66SMatthew G. Knepley           ierr = DMPlexMatSetClosure(dm, section, globalSection, Jac, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2643be36d101SStefano Zampini         } else {
2644be36d101SStefano Zampini           Mat lJ;
2645be36d101SStefano Zampini 
2646be36d101SStefano Zampini           ierr = MatISGetLocalMat(Jac,&lJ);CHKERRQ(ierr);
26479044fa66SMatthew G. Knepley           ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2648be36d101SStefano Zampini         }
2649efc10488SMatthew G. Knepley       }
26509044fa66SMatthew G. Knepley       if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMatP[cind*totDim*totDim]);CHKERRQ(ierr);}
2651be36d101SStefano Zampini       if (!isMatISP) {
26529044fa66SMatthew G. Knepley         ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, cell, &elemMatP[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
265355ad3c34SMatthew G. Knepley       } else {
2654be36d101SStefano Zampini         Mat lJ;
2655be36d101SStefano Zampini 
2656be36d101SStefano Zampini         ierr = MatISGetLocalMat(JacP,&lJ);CHKERRQ(ierr);
26579044fa66SMatthew G. Knepley         ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, cell, &elemMatP[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2658be36d101SStefano Zampini       }
2659be36d101SStefano Zampini     } else {
26609044fa66SMatthew G. Knepley       if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr);}
2661be36d101SStefano Zampini       if (!isMatISP) {
26629044fa66SMatthew G. Knepley         ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2663be36d101SStefano Zampini       } else {
2664be36d101SStefano Zampini         Mat lJ;
2665be36d101SStefano Zampini 
2666be36d101SStefano Zampini         ierr = MatISGetLocalMat(JacP,&lJ);CHKERRQ(ierr);
26679044fa66SMatthew G. Knepley         ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);
2668be36d101SStefano Zampini       }
266924cdb843SMatthew G. Knepley     }
267055ad3c34SMatthew G. Knepley   }
26719044fa66SMatthew G. Knepley   ierr = ISRestorePointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
26725244db28SMatthew G. Knepley   if (hasFV) {ierr = MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE);CHKERRQ(ierr);}
2673426ff135SMatthew G. Knepley   ierr = PetscFree5(u,u_t,elemMat,elemMatP,elemMatD);CHKERRQ(ierr);
2674f7ed7b21SMatthew G. Knepley   if (dmAux) {
2675f7ed7b21SMatthew G. Knepley     ierr = PetscFree(a);CHKERRQ(ierr);
2676f7ed7b21SMatthew G. Knepley     ierr = DMDestroy(&plex);CHKERRQ(ierr);
2677f7ed7b21SMatthew G. Knepley   }
26785bf53532SMatthew G. Knepley   /* Compute boundary integrals */
2679089bfe53SSander Arens   ierr = DMPlexComputeBdJacobian_Internal(dm, X, X_t, t, X_tShift, Jac, JacP, user);CHKERRQ(ierr);
26805bf53532SMatthew G. Knepley   /* Assemble matrix */
2681efc10488SMatthew G. Knepley   if (hasJac && hasPrec) {
268282ef7567SMatthew G. Knepley     ierr = MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
268382ef7567SMatthew G. Knepley     ierr = MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
268482ef7567SMatthew G. Knepley   }
268524cdb843SMatthew G. Knepley   ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
268624cdb843SMatthew G. Knepley   ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
268724cdb843SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
268824cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
268924cdb843SMatthew G. Knepley }
269024cdb843SMatthew G. Knepley 
26914a3e9fdbSToby Isaac PetscErrorCode DMPlexComputeJacobianAction_Internal(DM dm, IS cellIS, PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Vec Y, Vec Z, void *user)
2692a925c78cSMatthew G. Knepley {
2693a925c78cSMatthew G. Knepley   DM_Plex          *mesh  = (DM_Plex *) dm->data;
2694a925c78cSMatthew G. Knepley   const char       *name  = "Jacobian";
2695a925c78cSMatthew G. Knepley   DM                dmAux, plex;
2696c330f8ffSToby Isaac   Vec               A;
2697a925c78cSMatthew G. Knepley   PetscDS           prob, probAux = NULL;
2698a925c78cSMatthew G. Knepley   PetscQuadrature   quad;
2699a925c78cSMatthew G. Knepley   PetscSection      section, globalSection, sectionAux;
2700a925c78cSMatthew G. Knepley   PetscScalar      *elemMat, *elemMatD, *u, *u_t, *a = NULL, *y, *z;
27019044fa66SMatthew G. Knepley   PetscInt          Nf, fieldI, fieldJ;
27024d0b9603SSander Arens   PetscInt          totDim, totDimAux = 0;
27039044fa66SMatthew G. Knepley   const PetscInt   *cells;
27049044fa66SMatthew G. Knepley   PetscInt          cStart, cEnd, numCells, c;
270575b37a90SMatthew G. Knepley   PetscBool         hasDyn;
2706c330f8ffSToby Isaac   DMField           coordField;
2707a925c78cSMatthew G. Knepley   PetscErrorCode    ierr;
2708a925c78cSMatthew G. Knepley 
2709a925c78cSMatthew G. Knepley   PetscFunctionBegin;
2710a925c78cSMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
2711a925c78cSMatthew G. Knepley   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
2712a925c78cSMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);
2713a925c78cSMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
2714a925c78cSMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
2715a925c78cSMatthew G. Knepley   ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr);
2716a925c78cSMatthew G. Knepley   hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
2717a925c78cSMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
27184a3e9fdbSToby Isaac   ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr);
27199044fa66SMatthew G. Knepley   ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
2720a925c78cSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr);
2721a925c78cSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr);
2722a925c78cSMatthew G. Knepley   if (dmAux) {
2723a925c78cSMatthew G. Knepley     ierr = DMConvert(dmAux, DMPLEX, &plex);CHKERRQ(ierr);
2724a925c78cSMatthew G. Knepley     ierr = DMGetDefaultSection(plex, &sectionAux);CHKERRQ(ierr);
2725a925c78cSMatthew G. Knepley     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
2726a925c78cSMatthew G. Knepley     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
2727a925c78cSMatthew G. Knepley   }
2728a925c78cSMatthew G. Knepley   ierr = VecSet(Z, 0.0);CHKERRQ(ierr);
2729a925c78cSMatthew G. Knepley   ierr = PetscMalloc6(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*totDim*totDim,&elemMat,hasDyn ? numCells*totDim*totDim : 0, &elemMatD,numCells*totDim,&y,totDim,&z);CHKERRQ(ierr);
2730a925c78cSMatthew G. Knepley   if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);}
27314a3e9fdbSToby Isaac   ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr);
2732a925c78cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
27339044fa66SMatthew G. Knepley     const PetscInt cell = cells ? cells[c] : c;
27349044fa66SMatthew G. Knepley     const PetscInt cind = c - cStart;
2735a925c78cSMatthew G. Knepley     PetscScalar   *x = NULL,  *x_t = NULL;
2736a925c78cSMatthew G. Knepley     PetscInt       i;
2737a925c78cSMatthew G. Knepley 
27389044fa66SMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
27399044fa66SMatthew G. Knepley     for (i = 0; i < totDim; ++i) u[cind*totDim+i] = x[i];
27409044fa66SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
2741a925c78cSMatthew G. Knepley     if (X_t) {
27429044fa66SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
27439044fa66SMatthew G. Knepley       for (i = 0; i < totDim; ++i) u_t[cind*totDim+i] = x_t[i];
27449044fa66SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
2745a925c78cSMatthew G. Knepley     }
2746a925c78cSMatthew G. Knepley     if (dmAux) {
27479044fa66SMatthew G. Knepley       ierr = DMPlexVecGetClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr);
27489044fa66SMatthew G. Knepley       for (i = 0; i < totDimAux; ++i) a[cind*totDimAux+i] = x[i];
27499044fa66SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr);
2750a925c78cSMatthew G. Knepley     }
27519044fa66SMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr);
27529044fa66SMatthew G. Knepley     for (i = 0; i < totDim; ++i) y[cind*totDim+i] = x[i];
27539044fa66SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr);
2754a925c78cSMatthew G. Knepley   }
2755a925c78cSMatthew G. Knepley   ierr = PetscMemzero(elemMat, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);
2756a925c78cSMatthew G. Knepley   if (hasDyn)  {ierr = PetscMemzero(elemMatD, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);}
2757a925c78cSMatthew G. Knepley   for (fieldI = 0; fieldI < Nf; ++fieldI) {
2758a925c78cSMatthew G. Knepley     PetscFE  fe;
2759c330f8ffSToby Isaac     PetscInt Nb;
2760a925c78cSMatthew G. Knepley     /* Conforming batches */
2761a925c78cSMatthew G. Knepley     PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
2762a925c78cSMatthew G. Knepley     /* Remainder */
2763c330f8ffSToby Isaac     PetscInt Nr, offset, Nq;
2764c330f8ffSToby Isaac     PetscQuadrature qGeom = NULL;
2765c330f8ffSToby Isaac     PetscBool   isAffine;
2766c330f8ffSToby Isaac     PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL;
2767a925c78cSMatthew G. Knepley 
2768a925c78cSMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
2769a925c78cSMatthew G. Knepley     ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
2770a925c78cSMatthew G. Knepley     ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
2771a925c78cSMatthew G. Knepley     ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
2772c330f8ffSToby Isaac     ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr);
2773c330f8ffSToby Isaac     if (isAffine) {
2774c330f8ffSToby Isaac       ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr);
2775c330f8ffSToby Isaac     }
2776c330f8ffSToby Isaac     if (!qGeom) {
2777c330f8ffSToby Isaac       ierr = PetscFEGetQuadrature(fe,&qGeom);CHKERRQ(ierr);
2778c330f8ffSToby Isaac       ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr);
2779c330f8ffSToby Isaac     }
2780c330f8ffSToby Isaac     ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
27814a3e9fdbSToby Isaac     ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
2782c330f8ffSToby Isaac     blockSize = Nb;
2783a925c78cSMatthew G. Knepley     batchSize = numBlocks * blockSize;
2784a925c78cSMatthew G. Knepley     ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
2785a925c78cSMatthew G. Knepley     numChunks = numCells / (numBatches*batchSize);
2786a925c78cSMatthew G. Knepley     Ne        = numChunks*numBatches*batchSize;
2787a925c78cSMatthew G. Knepley     Nr        = numCells % (numBatches*batchSize);
2788a925c78cSMatthew G. Knepley     offset    = numCells - Nr;
2789c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr);
2790c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr);
2791a925c78cSMatthew G. Knepley     for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
2792f99c8401SToby Isaac       ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr);
2793f99c8401SToby Isaac       ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMat[offset*totDim*totDim]);CHKERRQ(ierr);
2794a925c78cSMatthew G. Knepley       if (hasDyn) {
2795f99c8401SToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr);
2796f99c8401SToby Isaac         ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMatD[offset*totDim*totDim]);CHKERRQ(ierr);
2797a925c78cSMatthew G. Knepley       }
2798a925c78cSMatthew G. Knepley     }
2799c330f8ffSToby Isaac     ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr);
2800c330f8ffSToby Isaac     ierr = PetscFEGeomRestoreChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr);
28014a3e9fdbSToby Isaac     ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
2802c330f8ffSToby Isaac     ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr);
2803a925c78cSMatthew G. Knepley   }
2804a925c78cSMatthew G. Knepley   if (hasDyn) {
28059044fa66SMatthew G. Knepley     for (c = 0; c < numCells*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c];
2806a925c78cSMatthew G. Knepley   }
2807a925c78cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
28089044fa66SMatthew G. Knepley     const PetscInt     cell = cells ? cells[c] : c;
28099044fa66SMatthew G. Knepley     const PetscInt     cind = c - cStart;
2810a925c78cSMatthew G. Knepley     const PetscBLASInt M = totDim, one = 1;
2811a925c78cSMatthew G. Knepley     const PetscScalar  a = 1.0, b = 0.0;
2812a925c78cSMatthew G. Knepley 
28139044fa66SMatthew G. Knepley     PetscStackCallBLAS("BLASgemv", BLASgemv_("N", &M, &M, &a, &elemMat[cind*totDim*totDim], &M, &y[cind*totDim], &one, &b, z, &one));
2814a925c78cSMatthew G. Knepley     if (mesh->printFEM > 1) {
28159044fa66SMatthew G. Knepley       ierr = DMPrintCellMatrix(c, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr);
28169044fa66SMatthew G. Knepley       ierr = DMPrintCellVector(c, "Y",  totDim, &y[cind*totDim]);CHKERRQ(ierr);
2817a925c78cSMatthew G. Knepley       ierr = DMPrintCellVector(c, "Z",  totDim, z);CHKERRQ(ierr);
2818a925c78cSMatthew G. Knepley     }
28199044fa66SMatthew G. Knepley     ierr = DMPlexVecSetClosure(dm, section, Z, cell, z, ADD_VALUES);CHKERRQ(ierr);
2820a925c78cSMatthew G. Knepley   }
2821a925c78cSMatthew G. Knepley   ierr = PetscFree6(u,u_t,elemMat,elemMatD,y,z);CHKERRQ(ierr);
2822a925c78cSMatthew G. Knepley   if (dmAux) {
2823a925c78cSMatthew G. Knepley     ierr = PetscFree(a);CHKERRQ(ierr);
2824a925c78cSMatthew G. Knepley     ierr = DMDestroy(&plex);CHKERRQ(ierr);
2825a925c78cSMatthew G. Knepley   }
2826a925c78cSMatthew G. Knepley   if (mesh->printFEM) {
2827a925c78cSMatthew G. Knepley     ierr = PetscPrintf(PETSC_COMM_WORLD, "Z:\n");CHKERRQ(ierr);
2828a925c78cSMatthew G. Knepley     ierr = VecView(Z, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
2829a925c78cSMatthew G. Knepley   }
2830a925c78cSMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
2831a925c78cSMatthew G. Knepley   PetscFunctionReturn(0);
2832a925c78cSMatthew G. Knepley }
2833a925c78cSMatthew G. Knepley 
283424cdb843SMatthew G. Knepley /*@
283524cdb843SMatthew G. Knepley   DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user.
283624cdb843SMatthew G. Knepley 
283724cdb843SMatthew G. Knepley   Input Parameters:
283824cdb843SMatthew G. Knepley + dm - The mesh
283924cdb843SMatthew G. Knepley . X  - Local input vector
284024cdb843SMatthew G. Knepley - user - The user context
284124cdb843SMatthew G. Knepley 
284224cdb843SMatthew G. Knepley   Output Parameter:
284324cdb843SMatthew G. Knepley . Jac  - Jacobian matrix
284424cdb843SMatthew G. Knepley 
284524cdb843SMatthew G. Knepley   Note:
284624cdb843SMatthew G. Knepley   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
284724cdb843SMatthew G. Knepley   like a GPU, or vectorize on a multicore machine.
284824cdb843SMatthew G. Knepley 
284924cdb843SMatthew G. Knepley   Level: developer
285024cdb843SMatthew G. Knepley 
285124cdb843SMatthew G. Knepley .seealso: FormFunctionLocal()
285224cdb843SMatthew G. Knepley @*/
285324cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user)
285424cdb843SMatthew G. Knepley {
28556da023fcSToby Isaac   DM             plex;
2856f04eb4edSMatthew G. Knepley   PetscDS        prob;
28574a3e9fdbSToby Isaac   IS             cellIS;
2858f04eb4edSMatthew G. Knepley   PetscBool      hasJac, hasPrec;
28594a3e9fdbSToby Isaac   PetscInt       depth;
286024cdb843SMatthew G. Knepley   PetscErrorCode ierr;
286124cdb843SMatthew G. Knepley 
286224cdb843SMatthew G. Knepley   PetscFunctionBegin;
28636da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
28644a3e9fdbSToby Isaac   ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
2865aeadca18SToby Isaac   ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr);
28669044fa66SMatthew G. Knepley   if (!cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr);}
2867f04eb4edSMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
2868f04eb4edSMatthew G. Knepley   ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr);
2869f04eb4edSMatthew G. Knepley   ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr);
2870f04eb4edSMatthew G. Knepley   if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);}
2871f04eb4edSMatthew G. Knepley   ierr = MatZeroEntries(JacP);CHKERRQ(ierr);
28724a3e9fdbSToby Isaac   ierr = DMPlexComputeJacobian_Internal(plex, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr);
28734a3e9fdbSToby Isaac   ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
28749a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
287524cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
287624cdb843SMatthew G. Knepley }
28771878804aSMatthew G. Knepley 
2878a925c78cSMatthew G. Knepley /*@
2879a925c78cSMatthew G. Knepley   DMPlexSNESComputeJacobianActionFEM - Form the local portion of the Jacobian action Z = J(X) Y at the local solution X using pointwise functions specified by the user.
2880a925c78cSMatthew G. Knepley 
2881a925c78cSMatthew G. Knepley   Input Parameters:
2882a925c78cSMatthew G. Knepley + dm - The mesh
2883a925c78cSMatthew G. Knepley . X  - Local solution vector
2884a925c78cSMatthew G. Knepley . Y  - Local input vector
2885a925c78cSMatthew G. Knepley - user - The user context
2886a925c78cSMatthew G. Knepley 
2887a925c78cSMatthew G. Knepley   Output Parameter:
2888a925c78cSMatthew G. Knepley . Z - Local output vector
2889a925c78cSMatthew G. Knepley 
2890a925c78cSMatthew G. Knepley   Note:
2891a925c78cSMatthew G. Knepley   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
2892a925c78cSMatthew G. Knepley   like a GPU, or vectorize on a multicore machine.
2893a925c78cSMatthew G. Knepley 
2894a925c78cSMatthew G. Knepley   Level: developer
2895a925c78cSMatthew G. Knepley 
2896a925c78cSMatthew G. Knepley .seealso: FormFunctionLocal()
2897a925c78cSMatthew G. Knepley @*/
2898a925c78cSMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianActionFEM(DM dm, Vec X, Vec Y, Vec Z, void *user)
2899a925c78cSMatthew G. Knepley {
2900a925c78cSMatthew G. Knepley   DM             plex;
29014a3e9fdbSToby Isaac   IS             cellIS;
29024a3e9fdbSToby Isaac   PetscInt       depth;
2903a925c78cSMatthew G. Knepley   PetscErrorCode ierr;
2904a925c78cSMatthew G. Knepley 
2905a925c78cSMatthew G. Knepley   PetscFunctionBegin;
2906a925c78cSMatthew G. Knepley   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
29074a3e9fdbSToby Isaac   ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
2908aeadca18SToby Isaac   ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr);
29094a3e9fdbSToby Isaac   if (!cellIS) {
29104a3e9fdbSToby Isaac     ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr);
29114a3e9fdbSToby Isaac   }
29124a3e9fdbSToby Isaac   ierr = DMPlexComputeJacobianAction_Internal(plex, cellIS, 0.0, 0.0, X, NULL, Y, Z, user);CHKERRQ(ierr);
2913c4e6da2cSBarry Smith   ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
2914a925c78cSMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
2915a925c78cSMatthew G. Knepley   PetscFunctionReturn(0);
2916a925c78cSMatthew G. Knepley }
2917a925c78cSMatthew G. Knepley 
29189f520fc2SToby Isaac /*@
29199f520fc2SToby Isaac   DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian.
29209f520fc2SToby Isaac 
29219f520fc2SToby Isaac   Input Parameters:
29229f520fc2SToby Isaac + dm - The DM object
2923dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary())
29249f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual())
29259f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian())
29261a244344SSatish Balay 
29271a244344SSatish Balay   Level: developer
29289f520fc2SToby Isaac @*/
29299f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx)
29309f520fc2SToby Isaac {
29319f520fc2SToby Isaac   PetscErrorCode ierr;
29329f520fc2SToby Isaac 
29339f520fc2SToby Isaac   PetscFunctionBegin;
29349f520fc2SToby Isaac   ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr);
29359f520fc2SToby Isaac   ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr);
29369f520fc2SToby Isaac   ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr);
29379f520fc2SToby Isaac   PetscFunctionReturn(0);
29389f520fc2SToby Isaac }
29399f520fc2SToby Isaac 
29400163fd50SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions_Internal(SNES snes, DM dm, Vec u, Vec sol, PetscErrorCode (**exactFuncs)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx), void **ctxs)
29411878804aSMatthew G. Knepley {
2942282e7bb4SMatthew G. Knepley   PetscDS        prob;
29431878804aSMatthew G. Knepley   Mat            J, M;
29441878804aSMatthew G. Knepley   Vec            r, b;
29451878804aSMatthew G. Knepley   MatNullSpace   nullSpace;
29461878804aSMatthew G. Knepley   PetscReal     *error, res = 0.0;
29471878804aSMatthew G. Knepley   PetscInt       numFields;
2948282e7bb4SMatthew G. Knepley   PetscBool      hasJac, hasPrec;
29491878804aSMatthew G. Knepley   PetscErrorCode ierr;
29501878804aSMatthew G. Knepley 
29511878804aSMatthew G. Knepley   PetscFunctionBegin;
29521878804aSMatthew G. Knepley   ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
29531878804aSMatthew G. Knepley   ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr);
29541878804aSMatthew G. Knepley   /* TODO Null space for J */
29551878804aSMatthew G. Knepley   /* Check discretization error */
29561878804aSMatthew G. Knepley   ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr);
29571878804aSMatthew G. Knepley   ierr = PetscMalloc1(PetscMax(1, numFields), &error);CHKERRQ(ierr);
29581878804aSMatthew G. Knepley   if (numFields > 1) {
29591878804aSMatthew G. Knepley     PetscInt f;
29601878804aSMatthew G. Knepley 
29611189c1efSToby Isaac     ierr = DMComputeL2FieldDiff(dm, 0.0, exactFuncs, ctxs, u, error);CHKERRQ(ierr);
29621878804aSMatthew G. Knepley     ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: [");CHKERRQ(ierr);
29631878804aSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
29641878804aSMatthew G. Knepley       if (f) {ierr = PetscPrintf(PETSC_COMM_WORLD, ", ");CHKERRQ(ierr);}
2965e5b268a4SToby Isaac       if (error[f] >= 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "%g", (double)error[f]);CHKERRQ(ierr);}
29661878804aSMatthew G. Knepley       else                     {ierr = PetscPrintf(PETSC_COMM_WORLD, "< 1.0e-11");CHKERRQ(ierr);}
29671878804aSMatthew G. Knepley     }
29681878804aSMatthew G. Knepley     ierr = PetscPrintf(PETSC_COMM_WORLD, "]\n");CHKERRQ(ierr);
29691878804aSMatthew G. Knepley   } else {
29700709b2feSToby Isaac     ierr = DMComputeL2Diff(dm, 0.0, exactFuncs, ctxs, u, &error[0]);CHKERRQ(ierr);
2971e5b268a4SToby Isaac     if (error[0] >= 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", (double)error[0]);CHKERRQ(ierr);}
29721878804aSMatthew G. Knepley     else                     {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);}
29731878804aSMatthew G. Knepley   }
29741878804aSMatthew G. Knepley   ierr = PetscFree(error);CHKERRQ(ierr);
29751878804aSMatthew G. Knepley   /* Check residual */
29761878804aSMatthew G. Knepley   ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr);
29771878804aSMatthew G. Knepley   ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr);
2978e5b268a4SToby Isaac   ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr);
29791878804aSMatthew G. Knepley   ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr);
29801878804aSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr);
2981685405a1SBarry Smith   ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr);
2982685405a1SBarry Smith   ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr);
29831878804aSMatthew G. Knepley   /* Check Jacobian */
2984282e7bb4SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
2985282e7bb4SMatthew G. Knepley   ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr);
2986282e7bb4SMatthew G. Knepley   ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr);
2987282e7bb4SMatthew G. Knepley   if (hasJac && hasPrec) {
2988282e7bb4SMatthew G. Knepley     ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr);
2989282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr);
2990282e7bb4SMatthew G. Knepley     ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr);
2991282e7bb4SMatthew G. Knepley     ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr);
2992282e7bb4SMatthew G. Knepley     ierr = MatDestroy(&M);CHKERRQ(ierr);
2993282e7bb4SMatthew G. Knepley   } else {
2994282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr);
2995282e7bb4SMatthew G. Knepley   }
2996282e7bb4SMatthew G. Knepley   ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr);
2997282e7bb4SMatthew G. Knepley   ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr);
29981878804aSMatthew G. Knepley   ierr = MatGetNullSpace(J, &nullSpace);CHKERRQ(ierr);
29991878804aSMatthew G. Knepley   if (nullSpace) {
30001878804aSMatthew G. Knepley     PetscBool isNull;
30011878804aSMatthew G. Knepley     ierr = MatNullSpaceTest(nullSpace, J, &isNull);CHKERRQ(ierr);
30021878804aSMatthew G. Knepley     if (!isNull) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid.");
30031878804aSMatthew G. Knepley   }
30041878804aSMatthew G. Knepley   ierr = VecDuplicate(u, &b);CHKERRQ(ierr);
30051878804aSMatthew G. Knepley   ierr = VecSet(r, 0.0);CHKERRQ(ierr);
30061878804aSMatthew G. Knepley   ierr = SNESComputeFunction(snes, r, b);CHKERRQ(ierr);
3007282e7bb4SMatthew G. Knepley   ierr = MatMult(J, u, r);CHKERRQ(ierr);
30081878804aSMatthew G. Knepley   ierr = VecAXPY(r, 1.0, b);CHKERRQ(ierr);
30091878804aSMatthew G. Knepley   ierr = VecDestroy(&b);CHKERRQ(ierr);
30101878804aSMatthew G. Knepley   ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr);
3011e5b268a4SToby Isaac   ierr = PetscPrintf(PETSC_COMM_WORLD, "Linear L_2 Residual: %g\n", (double)res);CHKERRQ(ierr);
30121878804aSMatthew G. Knepley   ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr);
30131878804aSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) r, "Au - b = Au + F(0)");CHKERRQ(ierr);
3014685405a1SBarry Smith   ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"linear_res_");CHKERRQ(ierr);
3015685405a1SBarry Smith   ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr);
30161878804aSMatthew G. Knepley   ierr = VecDestroy(&r);CHKERRQ(ierr);
30171878804aSMatthew G. Knepley   ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr);
30181878804aSMatthew G. Knepley   ierr = MatDestroy(&J);CHKERRQ(ierr);
30191878804aSMatthew G. Knepley   PetscFunctionReturn(0);
30201878804aSMatthew G. Knepley }
30211878804aSMatthew G. Knepley 
30220163fd50SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u, PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx), void **ctxs)
30231878804aSMatthew G. Knepley {
30241878804aSMatthew G. Knepley   DM             dm;
30251878804aSMatthew G. Knepley   Vec            sol;
30261878804aSMatthew G. Knepley   PetscBool      check;
30271878804aSMatthew G. Knepley   PetscErrorCode ierr;
30281878804aSMatthew G. Knepley 
30291878804aSMatthew G. Knepley   PetscFunctionBegin;
3030c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr);
30311878804aSMatthew G. Knepley   if (!check) PetscFunctionReturn(0);
30321878804aSMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
30331878804aSMatthew G. Knepley   ierr = VecDuplicate(u, &sol);CHKERRQ(ierr);
30341878804aSMatthew G. Knepley   ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr);
30351878804aSMatthew G. Knepley   ierr = DMSNESCheckFromOptions_Internal(snes, dm, u, sol, exactFuncs, ctxs);CHKERRQ(ierr);
30361878804aSMatthew G. Knepley   ierr = VecDestroy(&sol);CHKERRQ(ierr);
3037552f7358SJed Brown   PetscFunctionReturn(0);
3038552f7358SJed Brown }
3039