xref: /petsc/src/snes/utils/dmplexsnes.c (revision cfe5744f0cadc021ee3b3b46b74dc5272bdedb00)
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>
4af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
5af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h>
6552f7358SJed Brown 
7649ef022SMatthew Knepley static void pressure_Private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8649ef022SMatthew Knepley                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
9649ef022SMatthew Knepley                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
10649ef022SMatthew Knepley                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar p[])
11649ef022SMatthew Knepley {
12649ef022SMatthew Knepley   p[0] = u[uOff[1]];
13649ef022SMatthew Knepley }
14649ef022SMatthew Knepley 
15649ef022SMatthew Knepley /*
16649ef022SMatthew Knepley   SNESCorrectDiscretePressure_Private - Add a vector in the nullspace to make the continuum integral of the pressure field equal to zero. This is normally used only to evaluate convergence rates for the pressure accurately.
17649ef022SMatthew Knepley 
18649ef022SMatthew Knepley   Collective on SNES
19649ef022SMatthew Knepley 
20649ef022SMatthew Knepley   Input Parameters:
21649ef022SMatthew Knepley + snes      - The SNES
22649ef022SMatthew Knepley . pfield    - The field number for pressure
23649ef022SMatthew Knepley . nullspace - The pressure nullspace
24649ef022SMatthew Knepley . u         - The solution vector
25649ef022SMatthew Knepley - ctx       - An optional user context
26649ef022SMatthew Knepley 
27649ef022SMatthew Knepley   Output Parameter:
28649ef022SMatthew Knepley . u         - The solution with a continuum pressure integral of zero
29649ef022SMatthew Knepley 
30649ef022SMatthew Knepley   Notes:
31649ef022SMatthew Knepley   If int(u) = a and int(n) = b, then int(u - a/b n) = a - a/b b = 0. We assume that the nullspace is a single vector given explicitly.
32649ef022SMatthew Knepley 
33649ef022SMatthew Knepley   Level: developer
34649ef022SMatthew Knepley 
35649ef022SMatthew Knepley .seealso: SNESConvergedCorrectPressure()
36649ef022SMatthew Knepley */
37649ef022SMatthew Knepley static PetscErrorCode SNESCorrectDiscretePressure_Private(SNES snes, PetscInt pfield, MatNullSpace nullspace, Vec u, void *ctx)
38649ef022SMatthew Knepley {
39649ef022SMatthew Knepley   DM             dm;
40649ef022SMatthew Knepley   PetscDS        ds;
41649ef022SMatthew Knepley   const Vec     *nullvecs;
42649ef022SMatthew Knepley   PetscScalar    pintd, *intc, *intn;
43649ef022SMatthew Knepley   MPI_Comm       comm;
44649ef022SMatthew Knepley   PetscInt       Nf, Nv;
45649ef022SMatthew Knepley   PetscErrorCode ierr;
46649ef022SMatthew Knepley 
47649ef022SMatthew Knepley   PetscFunctionBegin;
48649ef022SMatthew Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
49649ef022SMatthew Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
502c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a SNES DM");
512c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!nullspace,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a Jacobian nullspace");
52649ef022SMatthew Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
53649ef022SMatthew Knepley   ierr = PetscDSSetObjective(ds, pfield, pressure_Private);CHKERRQ(ierr);
54649ef022SMatthew Knepley   ierr = MatNullSpaceGetVecs(nullspace, NULL, &Nv, &nullvecs);CHKERRQ(ierr);
552c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nv != 1,comm, PETSC_ERR_ARG_OUTOFRANGE, "Can only handle a single null vector for pressure, not %D", Nv);
56649ef022SMatthew Knepley   ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr);
572c71b3e2SJacob Faibussowitsch   PetscCheckFalse(PetscAbsScalar(pintd) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Discrete integral of pressure: %g", (double) PetscRealPart(pintd));
58649ef022SMatthew Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
59649ef022SMatthew Knepley   ierr = PetscMalloc2(Nf, &intc, Nf, &intn);CHKERRQ(ierr);
60649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, nullvecs[0], intn, ctx);CHKERRQ(ierr);
61649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr);
62649ef022SMatthew Knepley   ierr = VecAXPY(u, -intc[pfield]/intn[pfield], nullvecs[0]);CHKERRQ(ierr);
63649ef022SMatthew Knepley #if defined (PETSC_USE_DEBUG)
64649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr);
652c71b3e2SJacob Faibussowitsch   PetscCheckFalse(PetscAbsScalar(intc[pfield]) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Continuum integral of pressure after correction: %g", (double) PetscRealPart(intc[pfield]));
66649ef022SMatthew Knepley #endif
67649ef022SMatthew Knepley   ierr = PetscFree2(intc, intn);CHKERRQ(ierr);
68649ef022SMatthew Knepley   PetscFunctionReturn(0);
69649ef022SMatthew Knepley }
70649ef022SMatthew Knepley 
71649ef022SMatthew Knepley /*@C
72649ef022SMatthew Knepley    SNESConvergedCorrectPressure - Convergence test that adds a vector in the nullspace to make the continuum integral of the pressure field equal to zero. This is normally used only to evaluate convergence rates for the pressure accurately. The convergence test itself just mimics SNESConvergedDefault().
73649ef022SMatthew Knepley 
74649ef022SMatthew Knepley    Logically Collective on SNES
75649ef022SMatthew Knepley 
76649ef022SMatthew Knepley    Input Parameters:
77649ef022SMatthew Knepley +  snes - the SNES context
78649ef022SMatthew Knepley .  it - the iteration (0 indicates before any Newton steps)
79649ef022SMatthew Knepley .  xnorm - 2-norm of current iterate
80649ef022SMatthew Knepley .  snorm - 2-norm of current step
81649ef022SMatthew Knepley .  fnorm - 2-norm of function at current iterate
82649ef022SMatthew Knepley -  ctx   - Optional user context
83649ef022SMatthew Knepley 
84649ef022SMatthew Knepley    Output Parameter:
85649ef022SMatthew Knepley .  reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
86649ef022SMatthew Knepley 
87649ef022SMatthew Knepley    Notes:
88649ef022SMatthew Knepley    In order to use this monitor, you must setup several PETSc structures. First fields must be added to the DM, and a PetscDS must be created with discretizations of those fields. We currently assume that the pressure field has index 1. The pressure field must have a nullspace, likely created using the DMSetNullSpaceConstructor() interface. Last we must be able to integrate the pressure over the domain, so the DM attached to the SNES must be a Plex at this time.
89649ef022SMatthew Knepley 
90649ef022SMatthew Knepley    Level: advanced
91649ef022SMatthew Knepley 
92649ef022SMatthew Knepley .seealso: SNESConvergedDefault(), SNESSetConvergenceTest(), DMSetNullSpaceConstructor()
93649ef022SMatthew Knepley @*/
94649ef022SMatthew Knepley PetscErrorCode SNESConvergedCorrectPressure(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *ctx)
95649ef022SMatthew Knepley {
96649ef022SMatthew Knepley   PetscBool      monitorIntegral = PETSC_FALSE;
97649ef022SMatthew Knepley   PetscErrorCode ierr;
98649ef022SMatthew Knepley 
99649ef022SMatthew Knepley   PetscFunctionBegin;
100649ef022SMatthew Knepley   ierr = SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx);CHKERRQ(ierr);
101649ef022SMatthew Knepley   if (monitorIntegral) {
102649ef022SMatthew Knepley     Mat          J;
103649ef022SMatthew Knepley     Vec          u;
104649ef022SMatthew Knepley     MatNullSpace nullspace;
105649ef022SMatthew Knepley     const Vec   *nullvecs;
106649ef022SMatthew Knepley     PetscScalar  pintd;
107649ef022SMatthew Knepley 
108649ef022SMatthew Knepley     ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr);
109649ef022SMatthew Knepley     ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr);
110649ef022SMatthew Knepley     ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
111649ef022SMatthew Knepley     ierr = MatNullSpaceGetVecs(nullspace, NULL, NULL, &nullvecs);CHKERRQ(ierr);
112649ef022SMatthew Knepley     ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr);
1137d3de750SJacob Faibussowitsch     ierr = PetscInfo(snes, "SNES: Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd));CHKERRQ(ierr);
114649ef022SMatthew Knepley   }
115649ef022SMatthew Knepley   if (*reason > 0) {
116649ef022SMatthew Knepley     Mat          J;
117649ef022SMatthew Knepley     Vec          u;
118649ef022SMatthew Knepley     MatNullSpace nullspace;
119649ef022SMatthew Knepley     PetscInt     pfield = 1;
120649ef022SMatthew Knepley 
121649ef022SMatthew Knepley     ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr);
122649ef022SMatthew Knepley     ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr);
123649ef022SMatthew Knepley     ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
124649ef022SMatthew Knepley     ierr = SNESCorrectDiscretePressure_Private(snes, pfield, nullspace, u, ctx);CHKERRQ(ierr);
125649ef022SMatthew Knepley   }
126649ef022SMatthew Knepley   PetscFunctionReturn(0);
127649ef022SMatthew Knepley }
128649ef022SMatthew Knepley 
12924cdb843SMatthew G. Knepley /************************** Interpolation *******************************/
13024cdb843SMatthew G. Knepley 
1316da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy)
1326da023fcSToby Isaac {
1336da023fcSToby Isaac   PetscBool      isPlex;
1346da023fcSToby Isaac   PetscErrorCode ierr;
1356da023fcSToby Isaac 
1366da023fcSToby Isaac   PetscFunctionBegin;
1376da023fcSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr);
1386da023fcSToby Isaac   if (isPlex) {
1396da023fcSToby Isaac     *plex = dm;
1406da023fcSToby Isaac     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
141f7148743SMatthew G. Knepley   } else {
142f7148743SMatthew G. Knepley     ierr = PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex);CHKERRQ(ierr);
143f7148743SMatthew G. Knepley     if (!*plex) {
1446da023fcSToby Isaac       ierr = DMConvert(dm,DMPLEX,plex);CHKERRQ(ierr);
145f7148743SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex);CHKERRQ(ierr);
1466da023fcSToby Isaac       if (copy) {
1476da023fcSToby Isaac         ierr = DMCopyDMSNES(dm, *plex);CHKERRQ(ierr);
1489a2a23afSMatthew G. Knepley         ierr = DMCopyAuxiliaryVec(dm, *plex);CHKERRQ(ierr);
1496da023fcSToby Isaac       }
150f7148743SMatthew G. Knepley     } else {
151f7148743SMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) *plex);CHKERRQ(ierr);
152f7148743SMatthew G. Knepley     }
1536da023fcSToby Isaac   }
1546da023fcSToby Isaac   PetscFunctionReturn(0);
1556da023fcSToby Isaac }
1566da023fcSToby Isaac 
1574267b1a3SMatthew G. Knepley /*@C
1584267b1a3SMatthew G. Knepley   DMInterpolationCreate - Creates a DMInterpolationInfo context
1594267b1a3SMatthew G. Knepley 
160d083f849SBarry Smith   Collective
1614267b1a3SMatthew G. Knepley 
1624267b1a3SMatthew G. Knepley   Input Parameter:
1634267b1a3SMatthew G. Knepley . comm - the communicator
1644267b1a3SMatthew G. Knepley 
1654267b1a3SMatthew G. Knepley   Output Parameter:
1664267b1a3SMatthew G. Knepley . ctx - the context
1674267b1a3SMatthew G. Knepley 
1684267b1a3SMatthew G. Knepley   Level: beginner
1694267b1a3SMatthew G. Knepley 
1704267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationDestroy()
1714267b1a3SMatthew G. Knepley @*/
1720adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx)
1730adebc6cSBarry Smith {
174552f7358SJed Brown   PetscErrorCode ierr;
175552f7358SJed Brown 
176552f7358SJed Brown   PetscFunctionBegin;
177552f7358SJed Brown   PetscValidPointer(ctx, 2);
17895dccacaSBarry Smith   ierr = PetscNew(ctx);CHKERRQ(ierr);
1791aa26658SKarl Rupp 
180552f7358SJed Brown   (*ctx)->comm   = comm;
181552f7358SJed Brown   (*ctx)->dim    = -1;
182552f7358SJed Brown   (*ctx)->nInput = 0;
1830298fd71SBarry Smith   (*ctx)->points = NULL;
1840298fd71SBarry Smith   (*ctx)->cells  = NULL;
185552f7358SJed Brown   (*ctx)->n      = -1;
1860298fd71SBarry Smith   (*ctx)->coords = NULL;
187552f7358SJed Brown   PetscFunctionReturn(0);
188552f7358SJed Brown }
189552f7358SJed Brown 
1904267b1a3SMatthew G. Knepley /*@C
1914267b1a3SMatthew G. Knepley   DMInterpolationSetDim - Sets the spatial dimension for the interpolation context
1924267b1a3SMatthew G. Knepley 
1934267b1a3SMatthew G. Knepley   Not collective
1944267b1a3SMatthew G. Knepley 
1954267b1a3SMatthew G. Knepley   Input Parameters:
1964267b1a3SMatthew G. Knepley + ctx - the context
1974267b1a3SMatthew G. Knepley - dim - the spatial dimension
1984267b1a3SMatthew G. Knepley 
1994267b1a3SMatthew G. Knepley   Level: intermediate
2004267b1a3SMatthew G. Knepley 
2014267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2024267b1a3SMatthew G. Knepley @*/
2030adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim)
2040adebc6cSBarry Smith {
205552f7358SJed Brown   PetscFunctionBegin;
2062c71b3e2SJacob Faibussowitsch   PetscCheckFalse((dim < 1) || (dim > 3),ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %D", dim);
207552f7358SJed Brown   ctx->dim = dim;
208552f7358SJed Brown   PetscFunctionReturn(0);
209552f7358SJed Brown }
210552f7358SJed Brown 
2114267b1a3SMatthew G. Knepley /*@C
2124267b1a3SMatthew G. Knepley   DMInterpolationGetDim - Gets the spatial dimension for the interpolation context
2134267b1a3SMatthew G. Knepley 
2144267b1a3SMatthew G. Knepley   Not collective
2154267b1a3SMatthew G. Knepley 
2164267b1a3SMatthew G. Knepley   Input Parameter:
2174267b1a3SMatthew G. Knepley . ctx - the context
2184267b1a3SMatthew G. Knepley 
2194267b1a3SMatthew G. Knepley   Output Parameter:
2204267b1a3SMatthew G. Knepley . dim - the spatial dimension
2214267b1a3SMatthew G. Knepley 
2224267b1a3SMatthew G. Knepley   Level: intermediate
2234267b1a3SMatthew G. Knepley 
2244267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2254267b1a3SMatthew G. Knepley @*/
2260adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim)
2270adebc6cSBarry Smith {
228552f7358SJed Brown   PetscFunctionBegin;
229552f7358SJed Brown   PetscValidIntPointer(dim, 2);
230552f7358SJed Brown   *dim = ctx->dim;
231552f7358SJed Brown   PetscFunctionReturn(0);
232552f7358SJed Brown }
233552f7358SJed Brown 
2344267b1a3SMatthew G. Knepley /*@C
2354267b1a3SMatthew G. Knepley   DMInterpolationSetDof - Sets the number of fields interpolated at a point for the interpolation context
2364267b1a3SMatthew G. Knepley 
2374267b1a3SMatthew G. Knepley   Not collective
2384267b1a3SMatthew G. Knepley 
2394267b1a3SMatthew G. Knepley   Input Parameters:
2404267b1a3SMatthew G. Knepley + ctx - the context
2414267b1a3SMatthew G. Knepley - dof - the number of fields
2424267b1a3SMatthew G. Knepley 
2434267b1a3SMatthew G. Knepley   Level: intermediate
2444267b1a3SMatthew G. Knepley 
2454267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2464267b1a3SMatthew G. Knepley @*/
2470adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof)
2480adebc6cSBarry Smith {
249552f7358SJed Brown   PetscFunctionBegin;
2502c71b3e2SJacob Faibussowitsch   PetscCheckFalse(dof < 1,ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %D", dof);
251552f7358SJed Brown   ctx->dof = dof;
252552f7358SJed Brown   PetscFunctionReturn(0);
253552f7358SJed Brown }
254552f7358SJed Brown 
2554267b1a3SMatthew G. Knepley /*@C
2564267b1a3SMatthew G. Knepley   DMInterpolationGetDof - Gets the number of fields interpolated at a point for the interpolation context
2574267b1a3SMatthew G. Knepley 
2584267b1a3SMatthew G. Knepley   Not collective
2594267b1a3SMatthew G. Knepley 
2604267b1a3SMatthew G. Knepley   Input Parameter:
2614267b1a3SMatthew G. Knepley . ctx - the context
2624267b1a3SMatthew G. Knepley 
2634267b1a3SMatthew G. Knepley   Output Parameter:
2644267b1a3SMatthew G. Knepley . dof - the number of fields
2654267b1a3SMatthew G. Knepley 
2664267b1a3SMatthew G. Knepley   Level: intermediate
2674267b1a3SMatthew G. Knepley 
2684267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2694267b1a3SMatthew G. Knepley @*/
2700adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof)
2710adebc6cSBarry Smith {
272552f7358SJed Brown   PetscFunctionBegin;
273552f7358SJed Brown   PetscValidIntPointer(dof, 2);
274552f7358SJed Brown   *dof = ctx->dof;
275552f7358SJed Brown   PetscFunctionReturn(0);
276552f7358SJed Brown }
277552f7358SJed Brown 
2784267b1a3SMatthew G. Knepley /*@C
2794267b1a3SMatthew G. Knepley   DMInterpolationAddPoints - Add points at which we will interpolate the fields
2804267b1a3SMatthew G. Knepley 
2814267b1a3SMatthew G. Knepley   Not collective
2824267b1a3SMatthew G. Knepley 
2834267b1a3SMatthew G. Knepley   Input Parameters:
2844267b1a3SMatthew G. Knepley + ctx    - the context
2854267b1a3SMatthew G. Knepley . n      - the number of points
2864267b1a3SMatthew G. Knepley - points - the coordinates for each point, an array of size n * dim
2874267b1a3SMatthew G. Knepley 
2884267b1a3SMatthew G. Knepley   Note: The coordinate information is copied.
2894267b1a3SMatthew G. Knepley 
2904267b1a3SMatthew G. Knepley   Level: intermediate
2914267b1a3SMatthew G. Knepley 
2924267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationCreate()
2934267b1a3SMatthew G. Knepley @*/
2940adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[])
2950adebc6cSBarry Smith {
296552f7358SJed Brown   PetscErrorCode ierr;
297552f7358SJed Brown 
298552f7358SJed Brown   PetscFunctionBegin;
2992c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ctx->dim < 0,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
3002c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ctx->points,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet");
301552f7358SJed Brown   ctx->nInput = n;
3021aa26658SKarl Rupp 
303785e854fSJed Brown   ierr = PetscMalloc1(n*ctx->dim, &ctx->points);CHKERRQ(ierr);
304580bdb30SBarry Smith   ierr = PetscArraycpy(ctx->points, points, n*ctx->dim);CHKERRQ(ierr);
305552f7358SJed Brown   PetscFunctionReturn(0);
306552f7358SJed Brown }
307552f7358SJed Brown 
3084267b1a3SMatthew G. Knepley /*@C
30952aa1562SMatthew G. Knepley   DMInterpolationSetUp - Compute spatial indices for point location during interpolation
3104267b1a3SMatthew G. Knepley 
3114267b1a3SMatthew G. Knepley   Collective on ctx
3124267b1a3SMatthew G. Knepley 
3134267b1a3SMatthew G. Knepley   Input Parameters:
3144267b1a3SMatthew G. Knepley + ctx - the context
3154267b1a3SMatthew G. Knepley . dm  - the DM for the function space used for interpolation
31652aa1562SMatthew G. Knepley . redundantPoints - If PETSC_TRUE, all processes are passing in the same array of points. Otherwise, points need to be communicated among processes.
3177deeda50SSatish Balay - ignoreOutsideDomain - If PETSC_TRUE, ignore points outside the domain, otherwise return an error
3184267b1a3SMatthew G. Knepley 
3194267b1a3SMatthew G. Knepley   Level: intermediate
3204267b1a3SMatthew G. Knepley 
3214267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
3224267b1a3SMatthew G. Knepley @*/
32352aa1562SMatthew G. Knepley PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints, PetscBool ignoreOutsideDomain)
3240adebc6cSBarry Smith {
325552f7358SJed Brown   MPI_Comm          comm = ctx->comm;
326552f7358SJed Brown   PetscScalar       *a;
327552f7358SJed Brown   PetscInt          p, q, i;
328552f7358SJed Brown   PetscMPIInt       rank, size;
329552f7358SJed Brown   PetscErrorCode    ierr;
330552f7358SJed Brown   Vec               pointVec;
3313a93e3b7SToby Isaac   PetscSF           cellSF;
332552f7358SJed Brown   PetscLayout       layout;
333552f7358SJed Brown   PetscReal         *globalPoints;
334cb313848SJed Brown   PetscScalar       *globalPointsScalar;
335552f7358SJed Brown   const PetscInt    *ranges;
336552f7358SJed Brown   PetscMPIInt       *counts, *displs;
3373a93e3b7SToby Isaac   const PetscSFNode *foundCells;
3383a93e3b7SToby Isaac   const PetscInt    *foundPoints;
339552f7358SJed Brown   PetscMPIInt       *foundProcs, *globalProcs;
3403a93e3b7SToby Isaac   PetscInt          n, N, numFound;
341552f7358SJed Brown 
34219436ca2SJed Brown   PetscFunctionBegin;
343064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
344ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
345ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
3462c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ctx->dim < 0,comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
34719436ca2SJed Brown   /* Locate points */
34819436ca2SJed Brown   n = ctx->nInput;
349552f7358SJed Brown   if (!redundantPoints) {
350552f7358SJed Brown     ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
351552f7358SJed Brown     ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
352552f7358SJed Brown     ierr = PetscLayoutSetLocalSize(layout, n);CHKERRQ(ierr);
353552f7358SJed Brown     ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
354552f7358SJed Brown     ierr = PetscLayoutGetSize(layout, &N);CHKERRQ(ierr);
355552f7358SJed Brown     /* Communicate all points to all processes */
356dcca6d9dSJed Brown     ierr = PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs);CHKERRQ(ierr);
357552f7358SJed Brown     ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
358552f7358SJed Brown     for (p = 0; p < size; ++p) {
359552f7358SJed Brown       counts[p] = (ranges[p+1] - ranges[p])*ctx->dim;
360552f7358SJed Brown       displs[p] = ranges[p]*ctx->dim;
361552f7358SJed Brown     }
362ffc4695bSBarry Smith     ierr = MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm);CHKERRMPI(ierr);
363552f7358SJed Brown   } else {
364552f7358SJed Brown     N = n;
365552f7358SJed Brown     globalPoints = ctx->points;
36638ea73c8SJed Brown     counts = displs = NULL;
36738ea73c8SJed Brown     layout = NULL;
368552f7358SJed Brown   }
369552f7358SJed Brown #if 0
370dcca6d9dSJed Brown   ierr = PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
37119436ca2SJed Brown   /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */
372552f7358SJed Brown #else
373cb313848SJed Brown #if defined(PETSC_USE_COMPLEX)
37446b3086cSToby Isaac   ierr = PetscMalloc1(N*ctx->dim,&globalPointsScalar);CHKERRQ(ierr);
37546b3086cSToby Isaac   for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i];
376cb313848SJed Brown #else
377cb313848SJed Brown   globalPointsScalar = globalPoints;
378cb313848SJed Brown #endif
37904706141SMatthew G Knepley   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec);CHKERRQ(ierr);
380dcca6d9dSJed Brown   ierr = PetscMalloc2(N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
3817b5f2079SMatthew G. Knepley   for (p = 0; p < N; ++p) {foundProcs[p] = size;}
3823a93e3b7SToby Isaac   cellSF = NULL;
3832d1fa6caSMatthew G. Knepley   ierr = DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF);CHKERRQ(ierr);
3843a93e3b7SToby Isaac   ierr = PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells);CHKERRQ(ierr);
385552f7358SJed Brown #endif
3863a93e3b7SToby Isaac   for (p = 0; p < numFound; ++p) {
3873a93e3b7SToby Isaac     if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank;
388552f7358SJed Brown   }
389552f7358SJed Brown   /* Let the lowest rank process own each point */
390820f2d46SBarry Smith   ierr   = MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm);CHKERRMPI(ierr);
391552f7358SJed Brown   ctx->n = 0;
392552f7358SJed Brown   for (p = 0; p < N; ++p) {
39352aa1562SMatthew G. Knepley     if (globalProcs[p] == size) {
3942c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!ignoreOutsideDomain,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));
395dd400576SPatrick Sanan       else if (rank == 0) ++ctx->n;
39652aa1562SMatthew G. Knepley     } else if (globalProcs[p] == rank) ++ctx->n;
397552f7358SJed Brown   }
398552f7358SJed Brown   /* Create coordinates vector and array of owned cells */
399785e854fSJed Brown   ierr = PetscMalloc1(ctx->n, &ctx->cells);CHKERRQ(ierr);
400552f7358SJed Brown   ierr = VecCreate(comm, &ctx->coords);CHKERRQ(ierr);
401552f7358SJed Brown   ierr = VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE);CHKERRQ(ierr);
402552f7358SJed Brown   ierr = VecSetBlockSize(ctx->coords, ctx->dim);CHKERRQ(ierr);
403c0dedaeaSBarry Smith   ierr = VecSetType(ctx->coords,VECSTANDARD);CHKERRQ(ierr);
404552f7358SJed Brown   ierr = VecGetArray(ctx->coords, &a);CHKERRQ(ierr);
405552f7358SJed Brown   for (p = 0, q = 0, i = 0; p < N; ++p) {
406552f7358SJed Brown     if (globalProcs[p] == rank) {
407552f7358SJed Brown       PetscInt d;
408552f7358SJed Brown 
4091aa26658SKarl Rupp       for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d];
410f317b747SMatthew G. Knepley       ctx->cells[q] = foundCells[q].index;
411f317b747SMatthew G. Knepley       ++q;
412552f7358SJed Brown     }
413dd400576SPatrick Sanan     if (globalProcs[p] == size && rank == 0) {
41452aa1562SMatthew G. Knepley       PetscInt d;
41552aa1562SMatthew G. Knepley 
41652aa1562SMatthew G. Knepley       for (d = 0; d < ctx->dim; ++d, ++i) a[i] = 0.;
41752aa1562SMatthew G. Knepley       ctx->cells[q] = -1;
41852aa1562SMatthew G. Knepley       ++q;
41952aa1562SMatthew G. Knepley     }
420552f7358SJed Brown   }
421552f7358SJed Brown   ierr = VecRestoreArray(ctx->coords, &a);CHKERRQ(ierr);
422552f7358SJed Brown #if 0
423552f7358SJed Brown   ierr = PetscFree3(foundCells,foundProcs,globalProcs);CHKERRQ(ierr);
424552f7358SJed Brown #else
425552f7358SJed Brown   ierr = PetscFree2(foundProcs,globalProcs);CHKERRQ(ierr);
4263a93e3b7SToby Isaac   ierr = PetscSFDestroy(&cellSF);CHKERRQ(ierr);
427552f7358SJed Brown   ierr = VecDestroy(&pointVec);CHKERRQ(ierr);
428552f7358SJed Brown #endif
429cb313848SJed Brown   if ((void*)globalPointsScalar != (void*)globalPoints) {ierr = PetscFree(globalPointsScalar);CHKERRQ(ierr);}
430d343d804SMatthew G. Knepley   if (!redundantPoints) {ierr = PetscFree3(globalPoints,counts,displs);CHKERRQ(ierr);}
431552f7358SJed Brown   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
432552f7358SJed Brown   PetscFunctionReturn(0);
433552f7358SJed Brown }
434552f7358SJed Brown 
4354267b1a3SMatthew G. Knepley /*@C
4364267b1a3SMatthew G. Knepley   DMInterpolationGetCoordinates - Gets a Vec with the coordinates of each interpolation point
4374267b1a3SMatthew G. Knepley 
4384267b1a3SMatthew G. Knepley   Collective on ctx
4394267b1a3SMatthew G. Knepley 
4404267b1a3SMatthew G. Knepley   Input Parameter:
4414267b1a3SMatthew G. Knepley . ctx - the context
4424267b1a3SMatthew G. Knepley 
4434267b1a3SMatthew G. Knepley   Output Parameter:
4444267b1a3SMatthew G. Knepley . coordinates  - the coordinates of interpolation points
4454267b1a3SMatthew G. Knepley 
4464267b1a3SMatthew G. Knepley   Note: The local vector entries correspond to interpolation points lying on this process, according to the associated DM. This is a borrowed vector that the user should not destroy.
4474267b1a3SMatthew G. Knepley 
4484267b1a3SMatthew G. Knepley   Level: intermediate
4494267b1a3SMatthew G. Knepley 
4504267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
4514267b1a3SMatthew G. Knepley @*/
4520adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates)
4530adebc6cSBarry Smith {
454552f7358SJed Brown   PetscFunctionBegin;
455552f7358SJed Brown   PetscValidPointer(coordinates, 2);
4562c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
457552f7358SJed Brown   *coordinates = ctx->coords;
458552f7358SJed Brown   PetscFunctionReturn(0);
459552f7358SJed Brown }
460552f7358SJed Brown 
4614267b1a3SMatthew G. Knepley /*@C
4624267b1a3SMatthew G. Knepley   DMInterpolationGetVector - Gets a Vec which can hold all the interpolated field values
4634267b1a3SMatthew G. Knepley 
4644267b1a3SMatthew G. Knepley   Collective on ctx
4654267b1a3SMatthew G. Knepley 
4664267b1a3SMatthew G. Knepley   Input Parameter:
4674267b1a3SMatthew G. Knepley . ctx - the context
4684267b1a3SMatthew G. Knepley 
4694267b1a3SMatthew G. Knepley   Output Parameter:
4704267b1a3SMatthew G. Knepley . v  - a vector capable of holding the interpolated field values
4714267b1a3SMatthew G. Knepley 
4724267b1a3SMatthew G. Knepley   Note: This vector should be returned using DMInterpolationRestoreVector().
4734267b1a3SMatthew G. Knepley 
4744267b1a3SMatthew G. Knepley   Level: intermediate
4754267b1a3SMatthew G. Knepley 
4764267b1a3SMatthew G. Knepley .seealso: DMInterpolationRestoreVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
4774267b1a3SMatthew G. Knepley @*/
4780adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v)
4790adebc6cSBarry Smith {
480552f7358SJed Brown   PetscErrorCode ierr;
481552f7358SJed Brown 
482552f7358SJed Brown   PetscFunctionBegin;
483552f7358SJed Brown   PetscValidPointer(v, 2);
4842c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
485552f7358SJed Brown   ierr = VecCreate(ctx->comm, v);CHKERRQ(ierr);
486552f7358SJed Brown   ierr = VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE);CHKERRQ(ierr);
487552f7358SJed Brown   ierr = VecSetBlockSize(*v, ctx->dof);CHKERRQ(ierr);
488c0dedaeaSBarry Smith   ierr = VecSetType(*v,VECSTANDARD);CHKERRQ(ierr);
489552f7358SJed Brown   PetscFunctionReturn(0);
490552f7358SJed Brown }
491552f7358SJed Brown 
4924267b1a3SMatthew G. Knepley /*@C
4934267b1a3SMatthew G. Knepley   DMInterpolationRestoreVector - Returns a Vec which can hold all the interpolated field values
4944267b1a3SMatthew G. Knepley 
4954267b1a3SMatthew G. Knepley   Collective on ctx
4964267b1a3SMatthew G. Knepley 
4974267b1a3SMatthew G. Knepley   Input Parameters:
4984267b1a3SMatthew G. Knepley + ctx - the context
4994267b1a3SMatthew G. Knepley - v  - a vector capable of holding the interpolated field values
5004267b1a3SMatthew G. Knepley 
5014267b1a3SMatthew G. Knepley   Level: intermediate
5024267b1a3SMatthew G. Knepley 
5034267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
5044267b1a3SMatthew G. Knepley @*/
5050adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v)
5060adebc6cSBarry Smith {
507552f7358SJed Brown   PetscErrorCode ierr;
508552f7358SJed Brown 
509552f7358SJed Brown   PetscFunctionBegin;
510552f7358SJed Brown   PetscValidPointer(v, 2);
5112c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
512552f7358SJed Brown   ierr = VecDestroy(v);CHKERRQ(ierr);
513552f7358SJed Brown   PetscFunctionReturn(0);
514552f7358SJed Brown }
515552f7358SJed Brown 
516*cfe5744fSMatthew G. Knepley static inline PetscErrorCode DMInterpolate_Segment_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
517*cfe5744fSMatthew G. Knepley {
518*cfe5744fSMatthew G. Knepley   PetscReal          v0, J, invJ, detJ;
519*cfe5744fSMatthew G. Knepley   const PetscInt     dof = ctx->dof;
520*cfe5744fSMatthew G. Knepley   const PetscScalar *coords;
521*cfe5744fSMatthew G. Knepley   PetscScalar       *a;
522*cfe5744fSMatthew G. Knepley   PetscInt           p;
523*cfe5744fSMatthew G. Knepley   PetscErrorCode     ierr;
524*cfe5744fSMatthew G. Knepley 
525*cfe5744fSMatthew G. Knepley   PetscFunctionBegin;
526*cfe5744fSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
527*cfe5744fSMatthew G. Knepley   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
528*cfe5744fSMatthew G. Knepley   for (p = 0; p < ctx->n; ++p) {
529*cfe5744fSMatthew G. Knepley     PetscInt     c = ctx->cells[p];
530*cfe5744fSMatthew G. Knepley     PetscScalar *x = NULL;
531*cfe5744fSMatthew G. Knepley     PetscReal    xir[1];
532*cfe5744fSMatthew G. Knepley     PetscInt     xSize, comp;
533*cfe5744fSMatthew G. Knepley 
534*cfe5744fSMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0, &J, &invJ, &detJ);CHKERRQ(ierr);
535*cfe5744fSMatthew G. Knepley     PetscCheck(detJ > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT, (double) detJ, c);
536*cfe5744fSMatthew G. Knepley     xir[0] = invJ*PetscRealPart(coords[p] - v0);
537*cfe5744fSMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
538*cfe5744fSMatthew G. Knepley     if (2*dof == xSize) {
539*cfe5744fSMatthew G. Knepley       for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp]*(1 - xir[0]) + x[1*dof+comp]*xir[0];
540*cfe5744fSMatthew G. Knepley     } else if (dof == xSize) {
541*cfe5744fSMatthew G. Knepley       for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp];
542*cfe5744fSMatthew G. Knepley     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input closure size %" PetscInt_FMT " must be either %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 2*dof, dof);
543*cfe5744fSMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
544*cfe5744fSMatthew G. Knepley   }
545*cfe5744fSMatthew G. Knepley   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
546*cfe5744fSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
547*cfe5744fSMatthew G. Knepley   PetscFunctionReturn(0);
548*cfe5744fSMatthew G. Knepley }
549*cfe5744fSMatthew G. Knepley 
5509fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
551a6dfd86eSKarl Rupp {
552552f7358SJed Brown   PetscReal      *v0, *J, *invJ, detJ;
55356044e6dSMatthew G. Knepley   const PetscScalar *coords;
55456044e6dSMatthew G. Knepley   PetscScalar    *a;
555552f7358SJed Brown   PetscInt       p;
556552f7358SJed Brown   PetscErrorCode ierr;
557552f7358SJed Brown 
558552f7358SJed Brown   PetscFunctionBegin;
559dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
56056044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
561552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
562552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
563552f7358SJed Brown     PetscInt     c = ctx->cells[p];
564a1e44745SMatthew G. Knepley     PetscScalar *x = NULL;
565552f7358SJed Brown     PetscReal    xi[4];
566552f7358SJed Brown     PetscInt     d, f, comp;
567552f7358SJed Brown 
5688e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
5692c71b3e2SJacob Faibussowitsch     PetscCheckFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c);
5700298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
5711aa26658SKarl Rupp     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
5721aa26658SKarl Rupp 
573552f7358SJed Brown     for (d = 0; d < ctx->dim; ++d) {
574552f7358SJed Brown       xi[d] = 0.0;
5751aa26658SKarl 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]);
5761aa26658SKarl 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];
577552f7358SJed Brown     }
5780298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
579552f7358SJed Brown   }
580552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
58156044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
582552f7358SJed Brown   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
583552f7358SJed Brown   PetscFunctionReturn(0);
584552f7358SJed Brown }
585552f7358SJed Brown 
5869fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
5877a1931ceSMatthew G. Knepley {
5887a1931ceSMatthew G. Knepley   PetscReal      *v0, *J, *invJ, detJ;
58956044e6dSMatthew G. Knepley   const PetscScalar *coords;
59056044e6dSMatthew G. Knepley   PetscScalar    *a;
5917a1931ceSMatthew G. Knepley   PetscInt       p;
5927a1931ceSMatthew G. Knepley   PetscErrorCode ierr;
5937a1931ceSMatthew G. Knepley 
5947a1931ceSMatthew G. Knepley   PetscFunctionBegin;
595dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
59656044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
5977a1931ceSMatthew G. Knepley   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
5987a1931ceSMatthew G. Knepley   for (p = 0; p < ctx->n; ++p) {
5997a1931ceSMatthew G. Knepley     PetscInt       c = ctx->cells[p];
6007a1931ceSMatthew G. Knepley     const PetscInt order[3] = {2, 1, 3};
6012584bbe8SMatthew G. Knepley     PetscScalar   *x = NULL;
6027a1931ceSMatthew G. Knepley     PetscReal      xi[4];
6037a1931ceSMatthew G. Knepley     PetscInt       d, f, comp;
6047a1931ceSMatthew G. Knepley 
6058e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
6062c71b3e2SJacob Faibussowitsch     PetscCheckFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c);
6077a1931ceSMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
6087a1931ceSMatthew G. Knepley     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
6097a1931ceSMatthew G. Knepley 
6107a1931ceSMatthew G. Knepley     for (d = 0; d < ctx->dim; ++d) {
6117a1931ceSMatthew G. Knepley       xi[d] = 0.0;
6127a1931ceSMatthew 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]);
6137a1931ceSMatthew 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];
6147a1931ceSMatthew G. Knepley     }
6157a1931ceSMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
6167a1931ceSMatthew G. Knepley   }
6177a1931ceSMatthew G. Knepley   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
61856044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
6197a1931ceSMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
6207a1931ceSMatthew G. Knepley   PetscFunctionReturn(0);
6217a1931ceSMatthew G. Knepley }
6227a1931ceSMatthew G. Knepley 
6239fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
624552f7358SJed Brown {
625552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
626552f7358SJed Brown   const PetscScalar x0        = vertices[0];
627552f7358SJed Brown   const PetscScalar y0        = vertices[1];
628552f7358SJed Brown   const PetscScalar x1        = vertices[2];
629552f7358SJed Brown   const PetscScalar y1        = vertices[3];
630552f7358SJed Brown   const PetscScalar x2        = vertices[4];
631552f7358SJed Brown   const PetscScalar y2        = vertices[5];
632552f7358SJed Brown   const PetscScalar x3        = vertices[6];
633552f7358SJed Brown   const PetscScalar y3        = vertices[7];
634552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
635552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
636552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
637552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
638552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
639552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
64056044e6dSMatthew G. Knepley   const PetscScalar *ref;
64156044e6dSMatthew G. Knepley   PetscScalar       *real;
642552f7358SJed Brown   PetscErrorCode    ierr;
643552f7358SJed Brown 
644552f7358SJed Brown   PetscFunctionBegin;
64556044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
646552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
647552f7358SJed Brown   {
648552f7358SJed Brown     const PetscScalar p0 = ref[0];
649552f7358SJed Brown     const PetscScalar p1 = ref[1];
650552f7358SJed Brown 
651552f7358SJed Brown     real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1;
652552f7358SJed Brown     real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1;
653552f7358SJed Brown   }
654552f7358SJed Brown   ierr = PetscLogFlops(28);CHKERRQ(ierr);
65556044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
656552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
657552f7358SJed Brown   PetscFunctionReturn(0);
658552f7358SJed Brown }
659552f7358SJed Brown 
660af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
6619fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
662552f7358SJed Brown {
663552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
664552f7358SJed Brown   const PetscScalar x0        = vertices[0];
665552f7358SJed Brown   const PetscScalar y0        = vertices[1];
666552f7358SJed Brown   const PetscScalar x1        = vertices[2];
667552f7358SJed Brown   const PetscScalar y1        = vertices[3];
668552f7358SJed Brown   const PetscScalar x2        = vertices[4];
669552f7358SJed Brown   const PetscScalar y2        = vertices[5];
670552f7358SJed Brown   const PetscScalar x3        = vertices[6];
671552f7358SJed Brown   const PetscScalar y3        = vertices[7];
672552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
673552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
67456044e6dSMatthew G. Knepley   const PetscScalar *ref;
675552f7358SJed Brown   PetscErrorCode    ierr;
676552f7358SJed Brown 
677552f7358SJed Brown   PetscFunctionBegin;
67856044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
679552f7358SJed Brown   {
680552f7358SJed Brown     const PetscScalar x       = ref[0];
681552f7358SJed Brown     const PetscScalar y       = ref[1];
682552f7358SJed Brown     const PetscInt    rows[2] = {0, 1};
683da80777bSKarl Rupp     PetscScalar       values[4];
684da80777bSKarl Rupp 
685da80777bSKarl Rupp     values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5;
686da80777bSKarl Rupp     values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5;
68794ab13aaSBarry Smith     ierr      = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr);
688552f7358SJed Brown   }
689552f7358SJed Brown   ierr = PetscLogFlops(30);CHKERRQ(ierr);
69056044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
69194ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
69294ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
693552f7358SJed Brown   PetscFunctionReturn(0);
694552f7358SJed Brown }
695552f7358SJed Brown 
6969fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
697a6dfd86eSKarl Rupp {
698fafc0619SMatthew G Knepley   DM                 dmCoord;
699de73a395SMatthew G. Knepley   PetscFE            fem = NULL;
700552f7358SJed Brown   SNES               snes;
701552f7358SJed Brown   KSP                ksp;
702552f7358SJed Brown   PC                 pc;
703552f7358SJed Brown   Vec                coordsLocal, r, ref, real;
704552f7358SJed Brown   Mat                J;
705716009bfSMatthew G. Knepley   PetscTabulation    T = NULL;
70656044e6dSMatthew G. Knepley   const PetscScalar *coords;
70756044e6dSMatthew G. Knepley   PetscScalar        *a;
708716009bfSMatthew G. Knepley   PetscReal          xir[2] = {0., 0.};
709de73a395SMatthew G. Knepley   PetscInt           Nf, p;
7105509d985SMatthew G. Knepley   const PetscInt     dof = ctx->dof;
711552f7358SJed Brown   PetscErrorCode     ierr;
712552f7358SJed Brown 
713552f7358SJed Brown   PetscFunctionBegin;
714de73a395SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
715716009bfSMatthew G. Knepley   if (Nf) {
716*cfe5744fSMatthew G. Knepley     PetscObject  obj;
717*cfe5744fSMatthew G. Knepley     PetscClassId id;
718*cfe5744fSMatthew G. Knepley 
719*cfe5744fSMatthew G. Knepley     ierr = DMGetField(dm, 0, NULL, &obj);CHKERRQ(ierr);
720*cfe5744fSMatthew G. Knepley     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
721*cfe5744fSMatthew G. Knepley     if (id == PETSCFE_CLASSID) {fem = (PetscFE) obj; ierr = PetscFECreateTabulation(fem, 1, 1, xir, 0, &T);CHKERRQ(ierr);}
722716009bfSMatthew G. Knepley   }
723552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
724fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
725552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
726552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr);
727552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
728552f7358SJed Brown   ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr);
729c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
730552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
731552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
732552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
733552f7358SJed Brown   ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr);
734552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
735552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
7360298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr);
7370298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr);
738552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
739552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
740552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
741552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
742552f7358SJed Brown 
74356044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
744552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
745552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
746a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
747552f7358SJed Brown     PetscScalar *xi;
748552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
749552f7358SJed Brown 
750552f7358SJed Brown     /* Can make this do all points at once */
7510298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
7522c71b3e2SJacob Faibussowitsch     PetscCheckFalse(4*2 != coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 4*2);
7530298fd71SBarry Smith     ierr   = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
7543ec1f749SStefano Zampini     ierr   = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr);
7553ec1f749SStefano Zampini     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr);
756552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
757552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
758552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
759552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
760552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
761552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
762cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
763cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
764*cfe5744fSMatthew G. Knepley     if (4*dof == xSize) {
765*cfe5744fSMatthew G. Knepley       for (comp = 0; comp < dof; ++comp)
766*cfe5744fSMatthew 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];
767*cfe5744fSMatthew G. Knepley     } else if (dof == xSize) {
768*cfe5744fSMatthew G. Knepley       for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp];
769*cfe5744fSMatthew G. Knepley     } else {
7705509d985SMatthew G. Knepley       PetscInt d;
7711aa26658SKarl Rupp 
7722c71b3e2SJacob Faibussowitsch       PetscCheck(fem, ctx->comm, PETSC_ERR_ARG_WRONG, "Cannot have a higher order interpolant if the discretization is not PetscFE");
7735509d985SMatthew G. Knepley       xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0;
774ef0bb6c7SMatthew G. Knepley       ierr = PetscFEComputeTabulation(fem, 1, xir, 0, T);CHKERRQ(ierr);
7755509d985SMatthew G. Knepley       for (comp = 0; comp < dof; ++comp) {
7765509d985SMatthew G. Knepley         a[p*dof+comp] = 0.0;
7775509d985SMatthew G. Knepley         for (d = 0; d < xSize/dof; ++d) {
778ef0bb6c7SMatthew G. Knepley           a[p*dof+comp] += x[d*dof+comp]*T->T[0][d*dof+comp];
7795509d985SMatthew G. Knepley         }
7805509d985SMatthew G. Knepley       }
7815509d985SMatthew G. Knepley     }
782552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
7830298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
7840298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
785552f7358SJed Brown   }
786ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr);
787552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
78856044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
789552f7358SJed Brown 
790552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
791552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
792552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
793552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
794552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
795552f7358SJed Brown   PetscFunctionReturn(0);
796552f7358SJed Brown }
797552f7358SJed Brown 
7989fbee547SJacob Faibussowitsch static inline PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
799552f7358SJed Brown {
800552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
801552f7358SJed Brown   const PetscScalar x0        = vertices[0];
802552f7358SJed Brown   const PetscScalar y0        = vertices[1];
803552f7358SJed Brown   const PetscScalar z0        = vertices[2];
8047a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
8057a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
8067a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
807552f7358SJed Brown   const PetscScalar x2        = vertices[6];
808552f7358SJed Brown   const PetscScalar y2        = vertices[7];
809552f7358SJed Brown   const PetscScalar z2        = vertices[8];
8107a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
8117a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
8127a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
813552f7358SJed Brown   const PetscScalar x4        = vertices[12];
814552f7358SJed Brown   const PetscScalar y4        = vertices[13];
815552f7358SJed Brown   const PetscScalar z4        = vertices[14];
816552f7358SJed Brown   const PetscScalar x5        = vertices[15];
817552f7358SJed Brown   const PetscScalar y5        = vertices[16];
818552f7358SJed Brown   const PetscScalar z5        = vertices[17];
819552f7358SJed Brown   const PetscScalar x6        = vertices[18];
820552f7358SJed Brown   const PetscScalar y6        = vertices[19];
821552f7358SJed Brown   const PetscScalar z6        = vertices[20];
822552f7358SJed Brown   const PetscScalar x7        = vertices[21];
823552f7358SJed Brown   const PetscScalar y7        = vertices[22];
824552f7358SJed Brown   const PetscScalar z7        = vertices[23];
825552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
826552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
827552f7358SJed Brown   const PetscScalar h_1       = z1 - z0;
828552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
829552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
830552f7358SJed Brown   const PetscScalar h_3       = z3 - z0;
831552f7358SJed Brown   const PetscScalar f_4       = x4 - x0;
832552f7358SJed Brown   const PetscScalar g_4       = y4 - y0;
833552f7358SJed Brown   const PetscScalar h_4       = z4 - z0;
834552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
835552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
836552f7358SJed Brown   const PetscScalar h_01      = z2 - z1 - z3 + z0;
837552f7358SJed Brown   const PetscScalar f_12      = x7 - x3 - x4 + x0;
838552f7358SJed Brown   const PetscScalar g_12      = y7 - y3 - y4 + y0;
839552f7358SJed Brown   const PetscScalar h_12      = z7 - z3 - z4 + z0;
840552f7358SJed Brown   const PetscScalar f_02      = x5 - x1 - x4 + x0;
841552f7358SJed Brown   const PetscScalar g_02      = y5 - y1 - y4 + y0;
842552f7358SJed Brown   const PetscScalar h_02      = z5 - z1 - z4 + z0;
843552f7358SJed Brown   const PetscScalar f_012     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
844552f7358SJed Brown   const PetscScalar g_012     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
845552f7358SJed Brown   const PetscScalar h_012     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
84656044e6dSMatthew G. Knepley   const PetscScalar *ref;
84756044e6dSMatthew G. Knepley   PetscScalar       *real;
848552f7358SJed Brown   PetscErrorCode    ierr;
849552f7358SJed Brown 
850552f7358SJed Brown   PetscFunctionBegin;
85156044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
852552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
853552f7358SJed Brown   {
854552f7358SJed Brown     const PetscScalar p0 = ref[0];
855552f7358SJed Brown     const PetscScalar p1 = ref[1];
856552f7358SJed Brown     const PetscScalar p2 = ref[2];
857552f7358SJed Brown 
858552f7358SJed 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;
859552f7358SJed 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;
860552f7358SJed 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;
861552f7358SJed Brown   }
862552f7358SJed Brown   ierr = PetscLogFlops(114);CHKERRQ(ierr);
86356044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
864552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
865552f7358SJed Brown   PetscFunctionReturn(0);
866552f7358SJed Brown }
867552f7358SJed Brown 
8689fbee547SJacob Faibussowitsch static inline PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
869552f7358SJed Brown {
870552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
871552f7358SJed Brown   const PetscScalar x0        = vertices[0];
872552f7358SJed Brown   const PetscScalar y0        = vertices[1];
873552f7358SJed Brown   const PetscScalar z0        = vertices[2];
8747a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
8757a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
8767a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
877552f7358SJed Brown   const PetscScalar x2        = vertices[6];
878552f7358SJed Brown   const PetscScalar y2        = vertices[7];
879552f7358SJed Brown   const PetscScalar z2        = vertices[8];
8807a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
8817a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
8827a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
883552f7358SJed Brown   const PetscScalar x4        = vertices[12];
884552f7358SJed Brown   const PetscScalar y4        = vertices[13];
885552f7358SJed Brown   const PetscScalar z4        = vertices[14];
886552f7358SJed Brown   const PetscScalar x5        = vertices[15];
887552f7358SJed Brown   const PetscScalar y5        = vertices[16];
888552f7358SJed Brown   const PetscScalar z5        = vertices[17];
889552f7358SJed Brown   const PetscScalar x6        = vertices[18];
890552f7358SJed Brown   const PetscScalar y6        = vertices[19];
891552f7358SJed Brown   const PetscScalar z6        = vertices[20];
892552f7358SJed Brown   const PetscScalar x7        = vertices[21];
893552f7358SJed Brown   const PetscScalar y7        = vertices[22];
894552f7358SJed Brown   const PetscScalar z7        = vertices[23];
895552f7358SJed Brown   const PetscScalar f_xy      = x2 - x1 - x3 + x0;
896552f7358SJed Brown   const PetscScalar g_xy      = y2 - y1 - y3 + y0;
897552f7358SJed Brown   const PetscScalar h_xy      = z2 - z1 - z3 + z0;
898552f7358SJed Brown   const PetscScalar f_yz      = x7 - x3 - x4 + x0;
899552f7358SJed Brown   const PetscScalar g_yz      = y7 - y3 - y4 + y0;
900552f7358SJed Brown   const PetscScalar h_yz      = z7 - z3 - z4 + z0;
901552f7358SJed Brown   const PetscScalar f_xz      = x5 - x1 - x4 + x0;
902552f7358SJed Brown   const PetscScalar g_xz      = y5 - y1 - y4 + y0;
903552f7358SJed Brown   const PetscScalar h_xz      = z5 - z1 - z4 + z0;
904552f7358SJed Brown   const PetscScalar f_xyz     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
905552f7358SJed Brown   const PetscScalar g_xyz     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
906552f7358SJed Brown   const PetscScalar h_xyz     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
90756044e6dSMatthew G. Knepley   const PetscScalar *ref;
908552f7358SJed Brown   PetscErrorCode    ierr;
909552f7358SJed Brown 
910552f7358SJed Brown   PetscFunctionBegin;
91156044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
912552f7358SJed Brown   {
913552f7358SJed Brown     const PetscScalar x       = ref[0];
914552f7358SJed Brown     const PetscScalar y       = ref[1];
915552f7358SJed Brown     const PetscScalar z       = ref[2];
916552f7358SJed Brown     const PetscInt    rows[3] = {0, 1, 2};
917da80777bSKarl Rupp     PetscScalar       values[9];
918da80777bSKarl Rupp 
919da80777bSKarl Rupp     values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0;
920da80777bSKarl Rupp     values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0;
921da80777bSKarl Rupp     values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0;
922da80777bSKarl Rupp     values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0;
923da80777bSKarl Rupp     values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0;
924da80777bSKarl Rupp     values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0;
925da80777bSKarl Rupp     values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0;
926da80777bSKarl Rupp     values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0;
927da80777bSKarl Rupp     values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0;
9281aa26658SKarl Rupp 
92994ab13aaSBarry Smith     ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr);
930552f7358SJed Brown   }
931552f7358SJed Brown   ierr = PetscLogFlops(152);CHKERRQ(ierr);
93256044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
93394ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
93494ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
935552f7358SJed Brown   PetscFunctionReturn(0);
936552f7358SJed Brown }
937552f7358SJed Brown 
9389fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
939a6dfd86eSKarl Rupp {
940fafc0619SMatthew G Knepley   DM             dmCoord;
941552f7358SJed Brown   SNES           snes;
942552f7358SJed Brown   KSP            ksp;
943552f7358SJed Brown   PC             pc;
944552f7358SJed Brown   Vec            coordsLocal, r, ref, real;
945552f7358SJed Brown   Mat            J;
94656044e6dSMatthew G. Knepley   const PetscScalar *coords;
94756044e6dSMatthew G. Knepley   PetscScalar    *a;
948552f7358SJed Brown   PetscInt       p;
949552f7358SJed Brown   PetscErrorCode ierr;
950552f7358SJed Brown 
951552f7358SJed Brown   PetscFunctionBegin;
952552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
953fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
954552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
955552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr);
956552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
957552f7358SJed Brown   ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr);
958c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
959552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
960552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
961552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
962552f7358SJed Brown   ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr);
963552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
964552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
9650298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr);
9660298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr);
967552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
968552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
969552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
970552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
971552f7358SJed Brown 
97256044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
973552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
974552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
975a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
976552f7358SJed Brown     PetscScalar *xi;
977cb313848SJed Brown     PetscReal    xir[3];
978552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
979552f7358SJed Brown 
980552f7358SJed Brown     /* Can make this do all points at once */
9810298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
982*cfe5744fSMatthew G. Knepley     PetscCheck(8*3 == coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid coordinate closure size %" PetscInt_FMT " should be %d", coordSize, 8*3);
9830298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
984*cfe5744fSMatthew G. Knepley     PetscCheck((8*ctx->dof == xSize) || (ctx->dof == xSize),ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input closure size %" PetscInt_FMT " should be %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 8*ctx->dof, ctx->dof);
9853ec1f749SStefano Zampini     ierr   = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr);
9863ec1f749SStefano Zampini     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr);
987552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
988552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
989552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
990552f7358SJed Brown     xi[2]  = coords[p*ctx->dim+2];
991552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
992552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
993552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
994cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
995cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
996cb313848SJed Brown     xir[2] = PetscRealPart(xi[2]);
997*cfe5744fSMatthew G. Knepley     if (8*ctx->dof == xSize) {
998552f7358SJed Brown       for (comp = 0; comp < ctx->dof; ++comp) {
999552f7358SJed Brown         a[p*ctx->dof+comp] =
1000cb313848SJed Brown           x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) +
10017a1931ceSMatthew G. Knepley           x[3*ctx->dof+comp]*    xir[0]*(1-xir[1])*(1-xir[2]) +
1002cb313848SJed Brown           x[2*ctx->dof+comp]*    xir[0]*    xir[1]*(1-xir[2]) +
10037a1931ceSMatthew G. Knepley           x[1*ctx->dof+comp]*(1-xir[0])*    xir[1]*(1-xir[2]) +
1004cb313848SJed Brown           x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*   xir[2] +
1005cb313848SJed Brown           x[5*ctx->dof+comp]*    xir[0]*(1-xir[1])*   xir[2] +
1006cb313848SJed Brown           x[6*ctx->dof+comp]*    xir[0]*    xir[1]*   xir[2] +
1007cb313848SJed Brown           x[7*ctx->dof+comp]*(1-xir[0])*    xir[1]*   xir[2];
1008552f7358SJed Brown       }
1009*cfe5744fSMatthew G. Knepley     } else {
1010*cfe5744fSMatthew G. Knepley       for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
1011*cfe5744fSMatthew G. Knepley     }
1012552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
10130298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
10140298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
1015552f7358SJed Brown   }
1016552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
101756044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
1018552f7358SJed Brown 
1019552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
1020552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
1021552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
1022552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
1023552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
1024552f7358SJed Brown   PetscFunctionReturn(0);
1025552f7358SJed Brown }
1026552f7358SJed Brown 
10274267b1a3SMatthew G. Knepley /*@C
10284267b1a3SMatthew G. Knepley   DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points.
10294267b1a3SMatthew G. Knepley 
1030552f7358SJed Brown   Input Parameters:
1031552f7358SJed Brown + ctx - The DMInterpolationInfo context
1032552f7358SJed Brown . dm  - The DM
1033552f7358SJed Brown - x   - The local vector containing the field to be interpolated
1034552f7358SJed Brown 
1035552f7358SJed Brown   Output Parameters:
1036552f7358SJed Brown . v   - The vector containing the interpolated values
10374267b1a3SMatthew G. Knepley 
10384267b1a3SMatthew G. Knepley   Note: A suitable v can be obtained using DMInterpolationGetVector().
10394267b1a3SMatthew G. Knepley 
10404267b1a3SMatthew G. Knepley   Level: beginner
10414267b1a3SMatthew G. Knepley 
10424267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationAddPoints(), DMInterpolationCreate()
10434267b1a3SMatthew G. Knepley @*/
10440adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v)
10450adebc6cSBarry Smith {
104666a0a883SMatthew G. Knepley   PetscDS        ds;
104766a0a883SMatthew G. Knepley   PetscInt       n, p, Nf, field;
104866a0a883SMatthew G. Knepley   PetscBool      useDS = PETSC_FALSE;
1049552f7358SJed Brown   PetscErrorCode ierr;
1050552f7358SJed Brown 
1051552f7358SJed Brown   PetscFunctionBegin;
1052552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1053552f7358SJed Brown   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
1054552f7358SJed Brown   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
1055552f7358SJed Brown   ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
10562c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != ctx->n*ctx->dof,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %D should be %D", n, ctx->n*ctx->dof);
105766a0a883SMatthew G. Knepley   if (!n) PetscFunctionReturn(0);
1058680d18d5SMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1059680d18d5SMatthew G. Knepley   if (ds) {
106066a0a883SMatthew G. Knepley     useDS = PETSC_TRUE;
1061680d18d5SMatthew G. Knepley     ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
1062680d18d5SMatthew G. Knepley     for (field = 0; field < Nf; ++field) {
106366a0a883SMatthew G. Knepley       PetscObject  obj;
1064680d18d5SMatthew G. Knepley       PetscClassId id;
1065680d18d5SMatthew G. Knepley 
106666a0a883SMatthew G. Knepley       ierr = PetscDSGetDiscretization(ds, field, &obj);CHKERRQ(ierr);
106766a0a883SMatthew G. Knepley       ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
106866a0a883SMatthew G. Knepley       if (id != PETSCFE_CLASSID) {useDS = PETSC_FALSE; break;}
106966a0a883SMatthew G. Knepley     }
107066a0a883SMatthew G. Knepley   }
107166a0a883SMatthew G. Knepley   if (useDS) {
107266a0a883SMatthew G. Knepley     const PetscScalar *coords;
107366a0a883SMatthew G. Knepley     PetscScalar       *interpolant;
107466a0a883SMatthew G. Knepley     PetscInt           cdim, d;
107566a0a883SMatthew G. Knepley 
107666a0a883SMatthew G. Knepley     ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
1077680d18d5SMatthew G. Knepley     ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
1078680d18d5SMatthew G. Knepley     ierr = VecGetArrayWrite(v, &interpolant);CHKERRQ(ierr);
1079680d18d5SMatthew G. Knepley     for (p = 0; p < ctx->n; ++p) {
108066a0a883SMatthew G. Knepley       PetscReal    pcoords[3], xi[3];
1081680d18d5SMatthew G. Knepley       PetscScalar *xa   = NULL;
108266a0a883SMatthew G. Knepley       PetscInt     coff = 0, foff = 0, clSize;
1083680d18d5SMatthew G. Knepley 
108452aa1562SMatthew G. Knepley       if (ctx->cells[p] < 0) continue;
1085680d18d5SMatthew G. Knepley       for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p*cdim+d]);
1086680d18d5SMatthew G. Knepley       ierr = DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi);CHKERRQ(ierr);
108766a0a883SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr);
108866a0a883SMatthew G. Knepley       for (field = 0; field < Nf; ++field) {
108966a0a883SMatthew G. Knepley         PetscTabulation T;
109066a0a883SMatthew G. Knepley         PetscFE         fe;
109166a0a883SMatthew G. Knepley 
109266a0a883SMatthew G. Knepley         ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
1093680d18d5SMatthew G. Knepley         ierr = PetscFECreateTabulation(fe, 1, 1, xi, 0, &T);CHKERRQ(ierr);
1094680d18d5SMatthew G. Knepley         {
1095680d18d5SMatthew G. Knepley           const PetscReal *basis = T->T[0];
1096680d18d5SMatthew G. Knepley           const PetscInt   Nb    = T->Nb;
1097680d18d5SMatthew G. Knepley           const PetscInt   Nc    = T->Nc;
109866a0a883SMatthew G. Knepley           PetscInt         f, fc;
109966a0a883SMatthew G. Knepley 
1100680d18d5SMatthew G. Knepley           for (fc = 0; fc < Nc; ++fc) {
110166a0a883SMatthew G. Knepley             interpolant[p*ctx->dof+coff+fc] = 0.0;
1102680d18d5SMatthew G. Knepley             for (f = 0; f < Nb; ++f) {
110366a0a883SMatthew G. Knepley               interpolant[p*ctx->dof+coff+fc] += xa[foff+f]*basis[(0*Nb + f)*Nc + fc];
1104552f7358SJed Brown             }
1105680d18d5SMatthew G. Knepley           }
110666a0a883SMatthew G. Knepley           coff += Nc;
110766a0a883SMatthew G. Knepley           foff += Nb;
1108680d18d5SMatthew G. Knepley         }
1109680d18d5SMatthew G. Knepley         ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr);
1110680d18d5SMatthew G. Knepley       }
111166a0a883SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr);
11122c71b3e2SJacob Faibussowitsch       PetscCheckFalse(coff != ctx->dof,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %D != %D dof specified for interpolation", coff, ctx->dof);
11132c71b3e2SJacob Faibussowitsch       PetscCheckFalse(foff != clSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total FE space size %D != %D closure size", foff, clSize);
111466a0a883SMatthew G. Knepley     }
1115680d18d5SMatthew G. Knepley     ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
111666a0a883SMatthew G. Knepley     ierr = VecRestoreArrayWrite(v, &interpolant);CHKERRQ(ierr);
111766a0a883SMatthew G. Knepley   } else {
111866a0a883SMatthew G. Knepley     DMPolytopeType ct;
111966a0a883SMatthew G. Knepley 
1120680d18d5SMatthew G. Knepley     /* TODO Check each cell individually */
1121680d18d5SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, ctx->cells[0], &ct);CHKERRQ(ierr);
1122680d18d5SMatthew G. Knepley     switch (ct) {
1123*cfe5744fSMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:       ierr = DMInterpolate_Segment_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1124680d18d5SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:      ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1125680d18d5SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL: ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1126680d18d5SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:   ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1127680d18d5SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:    ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1128*cfe5744fSMatthew G. Knepley       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for cell type %s", DMPolytopeTypes[PetscMax(0, PetscMin(ct, DM_NUM_POLYTOPES))]);
1129680d18d5SMatthew G. Knepley     }
1130552f7358SJed Brown   }
1131552f7358SJed Brown   PetscFunctionReturn(0);
1132552f7358SJed Brown }
1133552f7358SJed Brown 
11344267b1a3SMatthew G. Knepley /*@C
11354267b1a3SMatthew G. Knepley   DMInterpolationDestroy - Destroys a DMInterpolationInfo context
11364267b1a3SMatthew G. Knepley 
11374267b1a3SMatthew G. Knepley   Collective on ctx
11384267b1a3SMatthew G. Knepley 
11394267b1a3SMatthew G. Knepley   Input Parameter:
11404267b1a3SMatthew G. Knepley . ctx - the context
11414267b1a3SMatthew G. Knepley 
11424267b1a3SMatthew G. Knepley   Level: beginner
11434267b1a3SMatthew G. Knepley 
11444267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
11454267b1a3SMatthew G. Knepley @*/
11460adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx)
11470adebc6cSBarry Smith {
1148552f7358SJed Brown   PetscErrorCode ierr;
1149552f7358SJed Brown 
1150552f7358SJed Brown   PetscFunctionBegin;
1151064a246eSJacob Faibussowitsch   PetscValidPointer(ctx, 1);
1152552f7358SJed Brown   ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr);
1153552f7358SJed Brown   ierr = PetscFree((*ctx)->points);CHKERRQ(ierr);
1154552f7358SJed Brown   ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr);
1155552f7358SJed Brown   ierr = PetscFree(*ctx);CHKERRQ(ierr);
11560298fd71SBarry Smith   *ctx = NULL;
1157552f7358SJed Brown   PetscFunctionReturn(0);
1158552f7358SJed Brown }
1159cc0c4584SMatthew G. Knepley 
1160cc0c4584SMatthew G. Knepley /*@C
1161cc0c4584SMatthew G. Knepley   SNESMonitorFields - Monitors the residual for each field separately
1162cc0c4584SMatthew G. Knepley 
1163cc0c4584SMatthew G. Knepley   Collective on SNES
1164cc0c4584SMatthew G. Knepley 
1165cc0c4584SMatthew G. Knepley   Input Parameters:
1166cc0c4584SMatthew G. Knepley + snes   - the SNES context
1167cc0c4584SMatthew G. Knepley . its    - iteration number
1168cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual
1169d43b4f6eSBarry Smith - vf  - PetscViewerAndFormat of type ASCII
1170cc0c4584SMatthew G. Knepley 
1171cc0c4584SMatthew G. Knepley   Notes:
1172cc0c4584SMatthew G. Knepley   This routine prints the residual norm at each iteration.
1173cc0c4584SMatthew G. Knepley 
1174cc0c4584SMatthew G. Knepley   Level: intermediate
1175cc0c4584SMatthew G. Knepley 
1176cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault()
1177cc0c4584SMatthew G. Knepley @*/
1178d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
1179cc0c4584SMatthew G. Knepley {
1180d43b4f6eSBarry Smith   PetscViewer        viewer = vf->viewer;
1181cc0c4584SMatthew G. Knepley   Vec                res;
1182cc0c4584SMatthew G. Knepley   DM                 dm;
1183cc0c4584SMatthew G. Knepley   PetscSection       s;
1184cc0c4584SMatthew G. Knepley   const PetscScalar *r;
1185cc0c4584SMatthew G. Knepley   PetscReal         *lnorms, *norms;
1186cc0c4584SMatthew G. Knepley   PetscInt           numFields, f, pStart, pEnd, p;
1187cc0c4584SMatthew G. Knepley   PetscErrorCode     ierr;
1188cc0c4584SMatthew G. Knepley 
1189cc0c4584SMatthew G. Knepley   PetscFunctionBegin;
11904d4332d5SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
11919e5d0892SLisandro Dalcin   ierr = SNESGetFunction(snes, &res, NULL, NULL);CHKERRQ(ierr);
1192cc0c4584SMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
119392fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
1194cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr);
1195cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1196cc0c4584SMatthew G. Knepley   ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr);
1197cc0c4584SMatthew G. Knepley   ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr);
1198cc0c4584SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
1199cc0c4584SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
1200cc0c4584SMatthew G. Knepley       PetscInt fdof, foff, d;
1201cc0c4584SMatthew G. Knepley 
1202cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr);
1203cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr);
1204cc0c4584SMatthew G. Knepley       for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d]));
1205cc0c4584SMatthew G. Knepley     }
1206cc0c4584SMatthew G. Knepley   }
1207cc0c4584SMatthew G. Knepley   ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr);
1208820f2d46SBarry Smith   ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);
1209d43b4f6eSBarry Smith   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
1210cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
1211cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr);
1212cc0c4584SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
1213cc0c4584SMatthew G. Knepley     if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
1214cc0c4584SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr);
1215cc0c4584SMatthew G. Knepley   }
1216cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr);
1217cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
1218d43b4f6eSBarry Smith   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1219cc0c4584SMatthew G. Knepley   ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr);
1220cc0c4584SMatthew G. Knepley   PetscFunctionReturn(0);
1221cc0c4584SMatthew G. Knepley }
122224cdb843SMatthew G. Knepley 
122324cdb843SMatthew G. Knepley /********************* Residual Computation **************************/
122424cdb843SMatthew G. Knepley 
12256528b96dSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
12266528b96dSMatthew G. Knepley {
12276528b96dSMatthew G. Knepley   PetscInt       depth;
12286528b96dSMatthew G. Knepley   PetscErrorCode ierr;
12296528b96dSMatthew G. Knepley 
12306528b96dSMatthew G. Knepley   PetscFunctionBegin;
12316528b96dSMatthew G. Knepley   ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
12326528b96dSMatthew G. Knepley   ierr = DMGetStratumIS(plex, "dim", depth, cellIS);CHKERRQ(ierr);
12336528b96dSMatthew G. Knepley   if (!*cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, cellIS);CHKERRQ(ierr);}
12346528b96dSMatthew G. Knepley   PetscFunctionReturn(0);
12356528b96dSMatthew G. Knepley }
12366528b96dSMatthew G. Knepley 
123724cdb843SMatthew G. Knepley /*@
12388db23a53SJed Brown   DMPlexSNESComputeResidualFEM - Sums the local residual into vector F from the local input X using pointwise functions specified by the user
123924cdb843SMatthew G. Knepley 
124024cdb843SMatthew G. Knepley   Input Parameters:
124124cdb843SMatthew G. Knepley + dm - The mesh
124224cdb843SMatthew G. Knepley . X  - Local solution
124324cdb843SMatthew G. Knepley - user - The user context
124424cdb843SMatthew G. Knepley 
124524cdb843SMatthew G. Knepley   Output Parameter:
124624cdb843SMatthew G. Knepley . F  - Local output vector
124724cdb843SMatthew G. Knepley 
12488db23a53SJed Brown   Notes:
12498db23a53SJed Brown   The residual is summed into F; the caller is responsible for using VecZeroEntries() or otherwise ensuring that any data in F is intentional.
12508db23a53SJed Brown 
125124cdb843SMatthew G. Knepley   Level: developer
125224cdb843SMatthew G. Knepley 
12537a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction()
125424cdb843SMatthew G. Knepley @*/
125524cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user)
125624cdb843SMatthew G. Knepley {
12576da023fcSToby Isaac   DM             plex;
1258083401c6SMatthew G. Knepley   IS             allcellIS;
12596528b96dSMatthew G. Knepley   PetscInt       Nds, s;
126024cdb843SMatthew G. Knepley   PetscErrorCode ierr;
126124cdb843SMatthew G. Knepley 
126224cdb843SMatthew G. Knepley   PetscFunctionBegin;
12636da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
12646528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
12656528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
12666528b96dSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
12676528b96dSMatthew G. Knepley     PetscDS          ds;
12686528b96dSMatthew G. Knepley     IS               cellIS;
126906ad1575SMatthew G. Knepley     PetscFormKey key;
12706528b96dSMatthew G. Knepley 
12716528b96dSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr);
12726528b96dSMatthew G. Knepley     key.value = 0;
12736528b96dSMatthew G. Knepley     key.field = 0;
127406ad1575SMatthew G. Knepley     key.part  = 0;
12756528b96dSMatthew G. Knepley     if (!key.label) {
12766528b96dSMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
12776528b96dSMatthew G. Knepley       cellIS = allcellIS;
12786528b96dSMatthew G. Knepley     } else {
12796528b96dSMatthew G. Knepley       IS pointIS;
12806528b96dSMatthew G. Knepley 
12816528b96dSMatthew G. Knepley       key.value = 1;
12826528b96dSMatthew G. Knepley       ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr);
12836528b96dSMatthew G. Knepley       ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
12846528b96dSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
12856528b96dSMatthew G. Knepley     }
12866528b96dSMatthew G. Knepley     ierr = DMPlexComputeResidual_Internal(plex, key, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);
12876528b96dSMatthew G. Knepley     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
12886528b96dSMatthew G. Knepley   }
12896528b96dSMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
12906528b96dSMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
12916528b96dSMatthew G. Knepley   PetscFunctionReturn(0);
12926528b96dSMatthew G. Knepley }
12936528b96dSMatthew G. Knepley 
12946528b96dSMatthew G. Knepley PetscErrorCode DMSNESComputeResidual(DM dm, Vec X, Vec F, void *user)
12956528b96dSMatthew G. Knepley {
12966528b96dSMatthew G. Knepley   DM             plex;
12976528b96dSMatthew G. Knepley   IS             allcellIS;
12986528b96dSMatthew G. Knepley   PetscInt       Nds, s;
12996528b96dSMatthew G. Knepley   PetscErrorCode ierr;
13006528b96dSMatthew G. Knepley 
13016528b96dSMatthew G. Knepley   PetscFunctionBegin;
13026528b96dSMatthew G. Knepley   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
13036528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
13046528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1305083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
1306083401c6SMatthew G. Knepley     PetscDS ds;
1307083401c6SMatthew G. Knepley     DMLabel label;
1308083401c6SMatthew G. Knepley     IS      cellIS;
1309083401c6SMatthew G. Knepley 
1310083401c6SMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr);
13116528b96dSMatthew G. Knepley     {
131206ad1575SMatthew G. Knepley       PetscWeakFormKind resmap[2] = {PETSC_WF_F0, PETSC_WF_F1};
13136528b96dSMatthew G. Knepley       PetscWeakForm     wf;
13146528b96dSMatthew G. Knepley       PetscInt          Nm = 2, m, Nk = 0, k, kp, off = 0;
131506ad1575SMatthew G. Knepley       PetscFormKey *reskeys;
13166528b96dSMatthew G. Knepley 
13176528b96dSMatthew G. Knepley       /* Get unique residual keys */
13186528b96dSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
13196528b96dSMatthew G. Knepley         PetscInt Nkm;
132006ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetSize(ds->wf->form[resmap[m]], &Nkm);CHKERRQ(ierr);
13216528b96dSMatthew G. Knepley         Nk  += Nkm;
13226528b96dSMatthew G. Knepley       }
13236528b96dSMatthew G. Knepley       ierr = PetscMalloc1(Nk, &reskeys);CHKERRQ(ierr);
13246528b96dSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
132506ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetKeys(ds->wf->form[resmap[m]], &off, reskeys);CHKERRQ(ierr);
13266528b96dSMatthew G. Knepley       }
13272c71b3e2SJacob Faibussowitsch       PetscCheckFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk);
132806ad1575SMatthew G. Knepley       ierr = PetscFormKeySort(Nk, reskeys);CHKERRQ(ierr);
13296528b96dSMatthew G. Knepley       for (k = 0, kp = 1; kp < Nk; ++kp) {
13306528b96dSMatthew G. Knepley         if ((reskeys[k].label != reskeys[kp].label) || (reskeys[k].value != reskeys[kp].value)) {
13316528b96dSMatthew G. Knepley           ++k;
13326528b96dSMatthew G. Knepley           if (kp != k) reskeys[k] = reskeys[kp];
13336528b96dSMatthew G. Knepley         }
13346528b96dSMatthew G. Knepley       }
13356528b96dSMatthew G. Knepley       Nk = k;
13366528b96dSMatthew G. Knepley 
13376528b96dSMatthew G. Knepley       ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
13386528b96dSMatthew G. Knepley       for (k = 0; k < Nk; ++k) {
13396528b96dSMatthew G. Knepley         DMLabel  label = reskeys[k].label;
13406528b96dSMatthew G. Knepley         PetscInt val   = reskeys[k].value;
13416528b96dSMatthew G. Knepley 
1342083401c6SMatthew G. Knepley         if (!label) {
1343083401c6SMatthew G. Knepley           ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
1344083401c6SMatthew G. Knepley           cellIS = allcellIS;
1345083401c6SMatthew G. Knepley         } else {
1346083401c6SMatthew G. Knepley           IS pointIS;
1347083401c6SMatthew G. Knepley 
13486528b96dSMatthew G. Knepley           ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr);
1349083401c6SMatthew G. Knepley           ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
1350083401c6SMatthew G. Knepley           ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
13514a3e9fdbSToby Isaac         }
13526528b96dSMatthew G. Knepley         ierr = DMPlexComputeResidual_Internal(plex, reskeys[k], cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);
13534a3e9fdbSToby Isaac         ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
1354083401c6SMatthew G. Knepley       }
13556528b96dSMatthew G. Knepley       ierr = PetscFree(reskeys);CHKERRQ(ierr);
13566528b96dSMatthew G. Knepley     }
13576528b96dSMatthew G. Knepley   }
1358083401c6SMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
13599a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
136024cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
136124cdb843SMatthew G. Knepley }
136224cdb843SMatthew G. Knepley 
1363bdd6f66aSToby Isaac /*@
1364bdd6f66aSToby Isaac   DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X
1365bdd6f66aSToby Isaac 
1366bdd6f66aSToby Isaac   Input Parameters:
1367bdd6f66aSToby Isaac + dm - The mesh
1368bdd6f66aSToby Isaac - user - The user context
1369bdd6f66aSToby Isaac 
1370bdd6f66aSToby Isaac   Output Parameter:
1371bdd6f66aSToby Isaac . X  - Local solution
1372bdd6f66aSToby Isaac 
1373bdd6f66aSToby Isaac   Level: developer
1374bdd6f66aSToby Isaac 
13757a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction()
1376bdd6f66aSToby Isaac @*/
1377bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user)
1378bdd6f66aSToby Isaac {
1379bdd6f66aSToby Isaac   DM             plex;
1380bdd6f66aSToby Isaac   PetscErrorCode ierr;
1381bdd6f66aSToby Isaac 
1382bdd6f66aSToby Isaac   PetscFunctionBegin;
1383bdd6f66aSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
1384bdd6f66aSToby Isaac   ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr);
1385bdd6f66aSToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
1386bdd6f66aSToby Isaac   PetscFunctionReturn(0);
1387bdd6f66aSToby Isaac }
1388bdd6f66aSToby Isaac 
13897a73cf09SMatthew G. Knepley /*@
13908e3a2eefSMatthew G. Knepley   DMSNESComputeJacobianAction - Compute the action of the Jacobian J(X) on Y
13917a73cf09SMatthew G. Knepley 
13927a73cf09SMatthew G. Knepley   Input Parameters:
13938e3a2eefSMatthew G. Knepley + dm   - The DM
13947a73cf09SMatthew G. Knepley . X    - Local solution vector
13957a73cf09SMatthew G. Knepley . Y    - Local input vector
13967a73cf09SMatthew G. Knepley - user - The user context
13977a73cf09SMatthew G. Knepley 
13987a73cf09SMatthew G. Knepley   Output Parameter:
13998e3a2eefSMatthew G. Knepley . F    - lcoal output vector
14007a73cf09SMatthew G. Knepley 
14017a73cf09SMatthew G. Knepley   Level: developer
14027a73cf09SMatthew G. Knepley 
14038e3a2eefSMatthew G. Knepley   Notes:
14048e3a2eefSMatthew G. Knepley   Users will typically use DMSNESCreateJacobianMF() followed by MatMult() instead of calling this routine directly.
14058e3a2eefSMatthew G. Knepley 
1406a509fe9cSSatish Balay .seealso: DMSNESCreateJacobianMF(), DMPlexSNESComputeResidualFEM()
14077a73cf09SMatthew G. Knepley @*/
14088e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESComputeJacobianAction(DM dm, Vec X, Vec Y, Vec F, void *user)
1409a925c78cSMatthew G. Knepley {
14108e3a2eefSMatthew G. Knepley   DM             plex;
14118e3a2eefSMatthew G. Knepley   IS             allcellIS;
14128e3a2eefSMatthew G. Knepley   PetscInt       Nds, s;
1413a925c78cSMatthew G. Knepley   PetscErrorCode ierr;
1414a925c78cSMatthew G. Knepley 
1415a925c78cSMatthew G. Knepley   PetscFunctionBegin;
14167a73cf09SMatthew G. Knepley   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
14178e3a2eefSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
14188e3a2eefSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
14198e3a2eefSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
14208e3a2eefSMatthew G. Knepley     PetscDS ds;
14218e3a2eefSMatthew G. Knepley     DMLabel label;
14228e3a2eefSMatthew G. Knepley     IS      cellIS;
14237a73cf09SMatthew G. Knepley 
14248e3a2eefSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr);
14258e3a2eefSMatthew G. Knepley     {
142606ad1575SMatthew G. Knepley       PetscWeakFormKind jacmap[4] = {PETSC_WF_G0, PETSC_WF_G1, PETSC_WF_G2, PETSC_WF_G3};
14278e3a2eefSMatthew G. Knepley       PetscWeakForm     wf;
14288e3a2eefSMatthew G. Knepley       PetscInt          Nm = 4, m, Nk = 0, k, kp, off = 0;
142906ad1575SMatthew G. Knepley       PetscFormKey *jackeys;
14308e3a2eefSMatthew G. Knepley 
14318e3a2eefSMatthew G. Knepley       /* Get unique Jacobian keys */
14328e3a2eefSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
14338e3a2eefSMatthew G. Knepley         PetscInt Nkm;
143406ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetSize(ds->wf->form[jacmap[m]], &Nkm);CHKERRQ(ierr);
14358e3a2eefSMatthew G. Knepley         Nk  += Nkm;
14368e3a2eefSMatthew G. Knepley       }
14378e3a2eefSMatthew G. Knepley       ierr = PetscMalloc1(Nk, &jackeys);CHKERRQ(ierr);
14388e3a2eefSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
143906ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetKeys(ds->wf->form[jacmap[m]], &off, jackeys);CHKERRQ(ierr);
14408e3a2eefSMatthew G. Knepley       }
14412c71b3e2SJacob Faibussowitsch       PetscCheckFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk);
144206ad1575SMatthew G. Knepley       ierr = PetscFormKeySort(Nk, jackeys);CHKERRQ(ierr);
14438e3a2eefSMatthew G. Knepley       for (k = 0, kp = 1; kp < Nk; ++kp) {
14448e3a2eefSMatthew G. Knepley         if ((jackeys[k].label != jackeys[kp].label) || (jackeys[k].value != jackeys[kp].value)) {
14458e3a2eefSMatthew G. Knepley           ++k;
14468e3a2eefSMatthew G. Knepley           if (kp != k) jackeys[k] = jackeys[kp];
14478e3a2eefSMatthew G. Knepley         }
14488e3a2eefSMatthew G. Knepley       }
14498e3a2eefSMatthew G. Knepley       Nk = k;
14508e3a2eefSMatthew G. Knepley 
14518e3a2eefSMatthew G. Knepley       ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
14528e3a2eefSMatthew G. Knepley       for (k = 0; k < Nk; ++k) {
14538e3a2eefSMatthew G. Knepley         DMLabel  label = jackeys[k].label;
14548e3a2eefSMatthew G. Knepley         PetscInt val   = jackeys[k].value;
14558e3a2eefSMatthew G. Knepley 
14568e3a2eefSMatthew G. Knepley         if (!label) {
14578e3a2eefSMatthew G. Knepley           ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
14588e3a2eefSMatthew G. Knepley           cellIS = allcellIS;
14597a73cf09SMatthew G. Knepley         } else {
14608e3a2eefSMatthew G. Knepley           IS pointIS;
1461a925c78cSMatthew G. Knepley 
14628e3a2eefSMatthew G. Knepley           ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr);
14638e3a2eefSMatthew G. Knepley           ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
14648e3a2eefSMatthew G. Knepley           ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1465a925c78cSMatthew G. Knepley         }
14668e3a2eefSMatthew G. Knepley         ierr = DMPlexComputeJacobian_Action_Internal(plex, jackeys[k], cellIS, 0.0, 0.0, X, NULL, Y, F, user);CHKERRQ(ierr);
14677a73cf09SMatthew G. Knepley         ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
14688e3a2eefSMatthew G. Knepley       }
14698e3a2eefSMatthew G. Knepley       ierr = PetscFree(jackeys);CHKERRQ(ierr);
14708e3a2eefSMatthew G. Knepley     }
14718e3a2eefSMatthew G. Knepley   }
14728e3a2eefSMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
14737a73cf09SMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
1474a925c78cSMatthew G. Knepley   PetscFunctionReturn(0);
1475a925c78cSMatthew G. Knepley }
1476a925c78cSMatthew G. Knepley 
147724cdb843SMatthew G. Knepley /*@
147824cdb843SMatthew G. Knepley   DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user.
147924cdb843SMatthew G. Knepley 
148024cdb843SMatthew G. Knepley   Input Parameters:
148124cdb843SMatthew G. Knepley + dm - The mesh
148224cdb843SMatthew G. Knepley . X  - Local input vector
148324cdb843SMatthew G. Knepley - user - The user context
148424cdb843SMatthew G. Knepley 
148524cdb843SMatthew G. Knepley   Output Parameter:
148624cdb843SMatthew G. Knepley . Jac  - Jacobian matrix
148724cdb843SMatthew G. Knepley 
148824cdb843SMatthew G. Knepley   Note:
148924cdb843SMatthew G. Knepley   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
149024cdb843SMatthew G. Knepley   like a GPU, or vectorize on a multicore machine.
149124cdb843SMatthew G. Knepley 
149224cdb843SMatthew G. Knepley   Level: developer
149324cdb843SMatthew G. Knepley 
149424cdb843SMatthew G. Knepley .seealso: FormFunctionLocal()
149524cdb843SMatthew G. Knepley @*/
149624cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user)
149724cdb843SMatthew G. Knepley {
14986da023fcSToby Isaac   DM             plex;
1499083401c6SMatthew G. Knepley   IS             allcellIS;
1500f04eb4edSMatthew G. Knepley   PetscBool      hasJac, hasPrec;
15016528b96dSMatthew G. Knepley   PetscInt       Nds, s;
150224cdb843SMatthew G. Knepley   PetscErrorCode ierr;
150324cdb843SMatthew G. Knepley 
150424cdb843SMatthew G. Knepley   PetscFunctionBegin;
15056da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
15066528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
15076528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1508083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
1509083401c6SMatthew G. Knepley     PetscDS          ds;
1510083401c6SMatthew G. Knepley     IS               cellIS;
151106ad1575SMatthew G. Knepley     PetscFormKey key;
1512083401c6SMatthew G. Knepley 
15136528b96dSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr);
15146528b96dSMatthew G. Knepley     key.value = 0;
15156528b96dSMatthew G. Knepley     key.field = 0;
151606ad1575SMatthew G. Knepley     key.part  = 0;
15176528b96dSMatthew G. Knepley     if (!key.label) {
1518083401c6SMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
1519083401c6SMatthew G. Knepley       cellIS = allcellIS;
1520083401c6SMatthew G. Knepley     } else {
1521083401c6SMatthew G. Knepley       IS pointIS;
1522083401c6SMatthew G. Knepley 
15236528b96dSMatthew G. Knepley       key.value = 1;
15246528b96dSMatthew G. Knepley       ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr);
1525083401c6SMatthew G. Knepley       ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
1526083401c6SMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1527083401c6SMatthew G. Knepley     }
1528083401c6SMatthew G. Knepley     if (!s) {
1529083401c6SMatthew G. Knepley       ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr);
1530083401c6SMatthew G. Knepley       ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr);
1531f04eb4edSMatthew G. Knepley       if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);}
1532f04eb4edSMatthew G. Knepley       ierr = MatZeroEntries(JacP);CHKERRQ(ierr);
1533083401c6SMatthew G. Knepley     }
15346528b96dSMatthew G. Knepley     ierr = DMPlexComputeJacobian_Internal(plex, key, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr);
15354a3e9fdbSToby Isaac     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
1536083401c6SMatthew G. Knepley   }
1537083401c6SMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
15389a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
153924cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
154024cdb843SMatthew G. Knepley }
15411878804aSMatthew G. Knepley 
15428e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx
15438e3a2eefSMatthew G. Knepley {
15448e3a2eefSMatthew G. Knepley   DM    dm;
15458e3a2eefSMatthew G. Knepley   Vec   X;
15468e3a2eefSMatthew G. Knepley   void *ctx;
15478e3a2eefSMatthew G. Knepley };
15488e3a2eefSMatthew G. Knepley 
15498e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Destroy_Private(Mat A)
15508e3a2eefSMatthew G. Knepley {
15518e3a2eefSMatthew G. Knepley   struct _DMSNESJacobianMFCtx *ctx;
15528e3a2eefSMatthew G. Knepley   PetscErrorCode               ierr;
15538e3a2eefSMatthew G. Knepley 
15548e3a2eefSMatthew G. Knepley   PetscFunctionBegin;
15553ec1f749SStefano Zampini   ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr);
15568e3a2eefSMatthew G. Knepley   ierr = MatShellSetContext(A, NULL);CHKERRQ(ierr);
15578e3a2eefSMatthew G. Knepley   ierr = DMDestroy(&ctx->dm);CHKERRQ(ierr);
15588e3a2eefSMatthew G. Knepley   ierr = VecDestroy(&ctx->X);CHKERRQ(ierr);
15598e3a2eefSMatthew G. Knepley   ierr = PetscFree(ctx);CHKERRQ(ierr);
15608e3a2eefSMatthew G. Knepley   PetscFunctionReturn(0);
15618e3a2eefSMatthew G. Knepley }
15628e3a2eefSMatthew G. Knepley 
15638e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Mult_Private(Mat A, Vec Y, Vec Z)
15648e3a2eefSMatthew G. Knepley {
15658e3a2eefSMatthew G. Knepley   struct _DMSNESJacobianMFCtx *ctx;
15668e3a2eefSMatthew G. Knepley   PetscErrorCode               ierr;
15678e3a2eefSMatthew G. Knepley 
15688e3a2eefSMatthew G. Knepley   PetscFunctionBegin;
15693ec1f749SStefano Zampini   ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr);
15708e3a2eefSMatthew G. Knepley   ierr = DMSNESComputeJacobianAction(ctx->dm, ctx->X, Y, Z, ctx->ctx);CHKERRQ(ierr);
15718e3a2eefSMatthew G. Knepley   PetscFunctionReturn(0);
15728e3a2eefSMatthew G. Knepley }
15738e3a2eefSMatthew G. Knepley 
15748e3a2eefSMatthew G. Knepley /*@
15758e3a2eefSMatthew G. Knepley   DMSNESCreateJacobianMF - Create a Mat which computes the action of the Jacobian matrix-free
15768e3a2eefSMatthew G. Knepley 
15778e3a2eefSMatthew G. Knepley   Collective on dm
15788e3a2eefSMatthew G. Knepley 
15798e3a2eefSMatthew G. Knepley   Input Parameters:
15808e3a2eefSMatthew G. Knepley + dm   - The DM
15818e3a2eefSMatthew G. Knepley . X    - The evaluation point for the Jacobian
15828e3a2eefSMatthew G. Knepley - user - A user context, or NULL
15838e3a2eefSMatthew G. Knepley 
15848e3a2eefSMatthew G. Knepley   Output Parameter:
15858e3a2eefSMatthew G. Knepley . J    - The Mat
15868e3a2eefSMatthew G. Knepley 
15878e3a2eefSMatthew G. Knepley   Level: advanced
15888e3a2eefSMatthew G. Knepley 
15898e3a2eefSMatthew G. Knepley   Notes:
15908e3a2eefSMatthew G. Knepley   Vec X is kept in Mat J, so updating X then updates the evaluation point.
15918e3a2eefSMatthew G. Knepley 
15928e3a2eefSMatthew G. Knepley .seealso: DMSNESComputeJacobianAction()
15938e3a2eefSMatthew G. Knepley @*/
15948e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESCreateJacobianMF(DM dm, Vec X, void *user, Mat *J)
15958e3a2eefSMatthew G. Knepley {
15968e3a2eefSMatthew G. Knepley   struct _DMSNESJacobianMFCtx *ctx;
15978e3a2eefSMatthew G. Knepley   PetscInt                     n, N;
15988e3a2eefSMatthew G. Knepley   PetscErrorCode               ierr;
15998e3a2eefSMatthew G. Knepley 
16008e3a2eefSMatthew G. Knepley   PetscFunctionBegin;
16018e3a2eefSMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dm), J);CHKERRQ(ierr);
16028e3a2eefSMatthew G. Knepley   ierr = MatSetType(*J, MATSHELL);CHKERRQ(ierr);
16038e3a2eefSMatthew G. Knepley   ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr);
16048e3a2eefSMatthew G. Knepley   ierr = VecGetSize(X, &N);CHKERRQ(ierr);
16058e3a2eefSMatthew G. Knepley   ierr = MatSetSizes(*J, n, n, N, N);CHKERRQ(ierr);
16068e3a2eefSMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
16078e3a2eefSMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) X);CHKERRQ(ierr);
16088e3a2eefSMatthew G. Knepley   ierr = PetscMalloc1(1, &ctx);CHKERRQ(ierr);
16098e3a2eefSMatthew G. Knepley   ctx->dm  = dm;
16108e3a2eefSMatthew G. Knepley   ctx->X   = X;
16118e3a2eefSMatthew G. Knepley   ctx->ctx = user;
16128e3a2eefSMatthew G. Knepley   ierr = MatShellSetContext(*J, ctx);CHKERRQ(ierr);
16138e3a2eefSMatthew G. Knepley   ierr = MatShellSetOperation(*J, MATOP_DESTROY, (void (*)(void)) DMSNESJacobianMF_Destroy_Private);CHKERRQ(ierr);
16148e3a2eefSMatthew G. Knepley   ierr = MatShellSetOperation(*J, MATOP_MULT,    (void (*)(void)) DMSNESJacobianMF_Mult_Private);CHKERRQ(ierr);
16158e3a2eefSMatthew G. Knepley   PetscFunctionReturn(0);
16168e3a2eefSMatthew G. Knepley }
16178e3a2eefSMatthew G. Knepley 
161838cfc46eSPierre Jolivet /*
161938cfc46eSPierre Jolivet      MatComputeNeumannOverlap - Computes an unassembled (Neumann) local overlapping Mat in nonlinear context.
162038cfc46eSPierre Jolivet 
162138cfc46eSPierre Jolivet    Input Parameters:
162238cfc46eSPierre Jolivet +     X - SNES linearization point
162338cfc46eSPierre Jolivet .     ovl - index set of overlapping subdomains
162438cfc46eSPierre Jolivet 
162538cfc46eSPierre Jolivet    Output Parameter:
162638cfc46eSPierre Jolivet .     J - unassembled (Neumann) local matrix
162738cfc46eSPierre Jolivet 
162838cfc46eSPierre Jolivet    Level: intermediate
162938cfc46eSPierre Jolivet 
163038cfc46eSPierre Jolivet .seealso: DMCreateNeumannOverlap(), MATIS, PCHPDDMSetAuxiliaryMat()
163138cfc46eSPierre Jolivet */
163238cfc46eSPierre Jolivet static PetscErrorCode MatComputeNeumannOverlap_Plex(Mat J, PetscReal t, Vec X, Vec X_t, PetscReal s, IS ovl, void *ctx)
163338cfc46eSPierre Jolivet {
163438cfc46eSPierre Jolivet   SNES           snes;
163538cfc46eSPierre Jolivet   Mat            pJ;
163638cfc46eSPierre Jolivet   DM             ovldm,origdm;
163738cfc46eSPierre Jolivet   DMSNES         sdm;
163838cfc46eSPierre Jolivet   PetscErrorCode (*bfun)(DM,Vec,void*);
163938cfc46eSPierre Jolivet   PetscErrorCode (*jfun)(DM,Vec,Mat,Mat,void*);
164038cfc46eSPierre Jolivet   void           *bctx,*jctx;
164138cfc46eSPierre Jolivet   PetscErrorCode ierr;
164238cfc46eSPierre Jolivet 
164338cfc46eSPierre Jolivet   PetscFunctionBegin;
164438cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_MATIS",(PetscObject*)&pJ);CHKERRQ(ierr);
16452c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!pJ,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing overlapping Mat");
164638cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Original_HPDDM",(PetscObject*)&origdm);CHKERRQ(ierr);
16472c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!origdm,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing original DM");
164838cfc46eSPierre Jolivet   ierr = MatGetDM(pJ,&ovldm);CHKERRQ(ierr);
164938cfc46eSPierre Jolivet   ierr = DMSNESGetBoundaryLocal(origdm,&bfun,&bctx);CHKERRQ(ierr);
165038cfc46eSPierre Jolivet   ierr = DMSNESSetBoundaryLocal(ovldm,bfun,bctx);CHKERRQ(ierr);
165138cfc46eSPierre Jolivet   ierr = DMSNESGetJacobianLocal(origdm,&jfun,&jctx);CHKERRQ(ierr);
165238cfc46eSPierre Jolivet   ierr = DMSNESSetJacobianLocal(ovldm,jfun,jctx);CHKERRQ(ierr);
165338cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject*)&snes);CHKERRQ(ierr);
165438cfc46eSPierre Jolivet   if (!snes) {
165538cfc46eSPierre Jolivet     ierr = SNESCreate(PetscObjectComm((PetscObject)ovl),&snes);CHKERRQ(ierr);
165638cfc46eSPierre Jolivet     ierr = SNESSetDM(snes,ovldm);CHKERRQ(ierr);
165738cfc46eSPierre Jolivet     ierr = PetscObjectCompose((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject)snes);CHKERRQ(ierr);
165838cfc46eSPierre Jolivet     ierr = PetscObjectDereference((PetscObject)snes);CHKERRQ(ierr);
165938cfc46eSPierre Jolivet   }
166038cfc46eSPierre Jolivet   ierr = DMGetDMSNES(ovldm,&sdm);CHKERRQ(ierr);
166138cfc46eSPierre Jolivet   ierr = VecLockReadPush(X);CHKERRQ(ierr);
166238cfc46eSPierre Jolivet   PetscStackPush("SNES user Jacobian function");
166338cfc46eSPierre Jolivet   ierr = (*sdm->ops->computejacobian)(snes,X,pJ,pJ,sdm->jacobianctx);CHKERRQ(ierr);
166438cfc46eSPierre Jolivet   PetscStackPop;
166538cfc46eSPierre Jolivet   ierr = VecLockReadPop(X);CHKERRQ(ierr);
166638cfc46eSPierre Jolivet   /* this is a no-hop, just in case we decide to change the placeholder for the local Neumann matrix */
166738cfc46eSPierre Jolivet   {
166838cfc46eSPierre Jolivet     Mat locpJ;
166938cfc46eSPierre Jolivet 
167038cfc46eSPierre Jolivet     ierr = MatISGetLocalMat(pJ,&locpJ);CHKERRQ(ierr);
167138cfc46eSPierre Jolivet     ierr = MatCopy(locpJ,J,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
167238cfc46eSPierre Jolivet   }
167338cfc46eSPierre Jolivet   PetscFunctionReturn(0);
167438cfc46eSPierre Jolivet }
167538cfc46eSPierre Jolivet 
1676a925c78cSMatthew G. Knepley /*@
16779f520fc2SToby Isaac   DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian.
16789f520fc2SToby Isaac 
16799f520fc2SToby Isaac   Input Parameters:
16809f520fc2SToby Isaac + dm - The DM object
1681dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary())
16829f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual())
16839f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian())
16841a244344SSatish Balay 
16851a244344SSatish Balay   Level: developer
16869f520fc2SToby Isaac @*/
16879f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx)
16889f520fc2SToby Isaac {
16899f520fc2SToby Isaac   PetscErrorCode ierr;
16909f520fc2SToby Isaac 
16919f520fc2SToby Isaac   PetscFunctionBegin;
16929f520fc2SToby Isaac   ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr);
16939f520fc2SToby Isaac   ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr);
16949f520fc2SToby Isaac   ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr);
169538cfc46eSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",MatComputeNeumannOverlap_Plex);CHKERRQ(ierr);
16969f520fc2SToby Isaac   PetscFunctionReturn(0);
16979f520fc2SToby Isaac }
16989f520fc2SToby Isaac 
1699f017bcb6SMatthew G. Knepley /*@C
1700f017bcb6SMatthew G. Knepley   DMSNESCheckDiscretization - Check the discretization error of the exact solution
1701f017bcb6SMatthew G. Knepley 
1702f017bcb6SMatthew G. Knepley   Input Parameters:
1703f017bcb6SMatthew G. Knepley + snes - the SNES object
1704f017bcb6SMatthew G. Knepley . dm   - the DM
1705f2cacb80SMatthew G. Knepley . t    - the time
1706f017bcb6SMatthew G. Knepley . u    - a DM vector
1707f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1708f017bcb6SMatthew G. Knepley 
1709f3c94560SMatthew G. Knepley   Output Parameters:
1710f3c94560SMatthew G. Knepley . error - An array which holds the discretization error in each field, or NULL
1711f3c94560SMatthew G. Knepley 
17127f96f943SMatthew G. Knepley   Note: The user must call PetscDSSetExactSolution() beforehand
17137f96f943SMatthew G. Knepley 
1714f017bcb6SMatthew G. Knepley   Level: developer
1715f017bcb6SMatthew G. Knepley 
17167f96f943SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckResidual(), DMSNESCheckJacobian(), PetscDSSetExactSolution()
1717f017bcb6SMatthew G. Knepley @*/
1718f2cacb80SMatthew G. Knepley PetscErrorCode DMSNESCheckDiscretization(SNES snes, DM dm, PetscReal t, Vec u, PetscReal tol, PetscReal error[])
17191878804aSMatthew G. Knepley {
1720f017bcb6SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
1721f017bcb6SMatthew G. Knepley   void            **ectxs;
1722f3c94560SMatthew G. Knepley   PetscReal        *err;
17237f96f943SMatthew G. Knepley   MPI_Comm          comm;
17247f96f943SMatthew G. Knepley   PetscInt          Nf, f;
17251878804aSMatthew G. Knepley   PetscErrorCode    ierr;
17261878804aSMatthew G. Knepley 
17271878804aSMatthew G. Knepley   PetscFunctionBegin;
1728f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1729f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1730064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(u, VEC_CLASSID, 4);
1731534a8f05SLisandro Dalcin   if (error) PetscValidRealPointer(error, 6);
17327f96f943SMatthew G. Knepley 
1733f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, t, u, NULL);CHKERRQ(ierr);
17347f96f943SMatthew G. Knepley   ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr);
17357f96f943SMatthew G. Knepley 
1736f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1737f017bcb6SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
1738083401c6SMatthew G. Knepley   ierr = PetscCalloc3(Nf, &exacts, Nf, &ectxs, PetscMax(1, Nf), &err);CHKERRQ(ierr);
17397f96f943SMatthew G. Knepley   {
17407f96f943SMatthew G. Knepley     PetscInt Nds, s;
17417f96f943SMatthew G. Knepley 
1742083401c6SMatthew G. Knepley     ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1743083401c6SMatthew G. Knepley     for (s = 0; s < Nds; ++s) {
17447f96f943SMatthew G. Knepley       PetscDS         ds;
1745083401c6SMatthew G. Knepley       DMLabel         label;
1746083401c6SMatthew G. Knepley       IS              fieldIS;
17477f96f943SMatthew G. Knepley       const PetscInt *fields;
17487f96f943SMatthew G. Knepley       PetscInt        dsNf, f;
1749083401c6SMatthew G. Knepley 
1750083401c6SMatthew G. Knepley       ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr);
1751083401c6SMatthew G. Knepley       ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr);
1752083401c6SMatthew G. Knepley       ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);
1753083401c6SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) {
1754083401c6SMatthew G. Knepley         const PetscInt field = fields[f];
1755083401c6SMatthew G. Knepley         ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr);
1756083401c6SMatthew G. Knepley       }
1757083401c6SMatthew G. Knepley       ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);
1758083401c6SMatthew G. Knepley     }
1759083401c6SMatthew G. Knepley   }
1760f017bcb6SMatthew G. Knepley   if (Nf > 1) {
1761f2cacb80SMatthew G. Knepley     ierr = DMComputeL2FieldDiff(dm, t, exacts, ectxs, u, err);CHKERRQ(ierr);
1762f017bcb6SMatthew G. Knepley     if (tol >= 0.0) {
1763f017bcb6SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
17642c71b3e2SJacob Faibussowitsch         PetscCheckFalse(err[f] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g for field %D exceeds tolerance %g", (double) err[f], f, (double) tol);
17651878804aSMatthew G. Knepley       }
1766b878532fSMatthew G. Knepley     } else if (error) {
1767b878532fSMatthew G. Knepley       for (f = 0; f < Nf; ++f) error[f] = err[f];
17681878804aSMatthew G. Knepley     } else {
1769f017bcb6SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr);
1770f017bcb6SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
1771f017bcb6SMatthew G. Knepley         if (f) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);}
1772f3c94560SMatthew G. Knepley         ierr = PetscPrintf(comm, "%g", (double)err[f]);CHKERRQ(ierr);
17731878804aSMatthew G. Knepley       }
1774f017bcb6SMatthew G. Knepley       ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr);
1775f017bcb6SMatthew G. Knepley     }
1776f017bcb6SMatthew G. Knepley   } else {
1777f2cacb80SMatthew G. Knepley     ierr = DMComputeL2Diff(dm, t, exacts, ectxs, u, &err[0]);CHKERRQ(ierr);
1778f017bcb6SMatthew G. Knepley     if (tol >= 0.0) {
17792c71b3e2SJacob Faibussowitsch       PetscCheckFalse(err[0] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g exceeds tolerance %g", (double) err[0], (double) tol);
1780b878532fSMatthew G. Knepley     } else if (error) {
1781b878532fSMatthew G. Knepley       error[0] = err[0];
1782f017bcb6SMatthew G. Knepley     } else {
1783f3c94560SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: %g\n", (double) err[0]);CHKERRQ(ierr);
1784f017bcb6SMatthew G. Knepley     }
1785f017bcb6SMatthew G. Knepley   }
1786f3c94560SMatthew G. Knepley   ierr = PetscFree3(exacts, ectxs, err);CHKERRQ(ierr);
1787f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1788f017bcb6SMatthew G. Knepley }
1789f017bcb6SMatthew G. Knepley 
1790f017bcb6SMatthew G. Knepley /*@C
1791f017bcb6SMatthew G. Knepley   DMSNESCheckResidual - Check the residual of the exact solution
1792f017bcb6SMatthew G. Knepley 
1793f017bcb6SMatthew G. Knepley   Input Parameters:
1794f017bcb6SMatthew G. Knepley + snes - the SNES object
1795f017bcb6SMatthew G. Knepley . dm   - the DM
1796f017bcb6SMatthew G. Knepley . u    - a DM vector
1797f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1798f017bcb6SMatthew G. Knepley 
1799f3c94560SMatthew G. Knepley   Output Parameters:
1800f3c94560SMatthew G. Knepley . residual - The residual norm of the exact solution, or NULL
1801f3c94560SMatthew G. Knepley 
1802f017bcb6SMatthew G. Knepley   Level: developer
1803f017bcb6SMatthew G. Knepley 
1804f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckJacobian()
1805f017bcb6SMatthew G. Knepley @*/
1806f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckResidual(SNES snes, DM dm, Vec u, PetscReal tol, PetscReal *residual)
1807f017bcb6SMatthew G. Knepley {
1808f017bcb6SMatthew G. Knepley   MPI_Comm       comm;
1809f017bcb6SMatthew G. Knepley   Vec            r;
1810f017bcb6SMatthew G. Knepley   PetscReal      res;
1811f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1812f017bcb6SMatthew G. Knepley 
1813f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1814f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1815f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1816f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
1817534a8f05SLisandro Dalcin   if (residual) PetscValidRealPointer(residual, 5);
1818f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1819f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr);
1820f017bcb6SMatthew G. Knepley   ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
18211878804aSMatthew G. Knepley   ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr);
18221878804aSMatthew G. Knepley   ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr);
1823f017bcb6SMatthew G. Knepley   if (tol >= 0.0) {
18242c71b3e2SJacob Faibussowitsch     PetscCheckFalse(res > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Residual %g exceeds tolerance %g", (double) res, (double) tol);
1825b878532fSMatthew G. Knepley   } else if (residual) {
1826b878532fSMatthew G. Knepley     *residual = res;
1827f017bcb6SMatthew G. Knepley   } else {
1828f017bcb6SMatthew G. Knepley     ierr = PetscPrintf(comm, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr);
18291878804aSMatthew G. Knepley     ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr);
18301878804aSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr);
1831685405a1SBarry Smith     ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr);
1832685405a1SBarry Smith     ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr);
1833f017bcb6SMatthew G. Knepley   }
1834f017bcb6SMatthew G. Knepley   ierr = VecDestroy(&r);CHKERRQ(ierr);
1835f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1836f017bcb6SMatthew G. Knepley }
1837f017bcb6SMatthew G. Knepley 
1838f017bcb6SMatthew G. Knepley /*@C
1839f3c94560SMatthew G. Knepley   DMSNESCheckJacobian - Check the Jacobian of the exact solution against the residual using the Taylor Test
1840f017bcb6SMatthew G. Knepley 
1841f017bcb6SMatthew G. Knepley   Input Parameters:
1842f017bcb6SMatthew G. Knepley + snes - the SNES object
1843f017bcb6SMatthew G. Knepley . dm   - the DM
1844f017bcb6SMatthew G. Knepley . u    - a DM vector
1845f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1846f017bcb6SMatthew G. Knepley 
1847f3c94560SMatthew G. Knepley   Output Parameters:
1848f3c94560SMatthew G. Knepley + isLinear - Flag indicaing that the function looks linear, or NULL
1849f3c94560SMatthew G. Knepley - convRate - The rate of convergence of the linear model, or NULL
1850f3c94560SMatthew G. Knepley 
1851f017bcb6SMatthew G. Knepley   Level: developer
1852f017bcb6SMatthew G. Knepley 
1853f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckResidual()
1854f017bcb6SMatthew G. Knepley @*/
1855f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckJacobian(SNES snes, DM dm, Vec u, PetscReal tol, PetscBool *isLinear, PetscReal *convRate)
1856f017bcb6SMatthew G. Knepley {
1857f017bcb6SMatthew G. Knepley   MPI_Comm       comm;
1858f017bcb6SMatthew G. Knepley   PetscDS        ds;
1859f017bcb6SMatthew G. Knepley   Mat            J, M;
1860f017bcb6SMatthew G. Knepley   MatNullSpace   nullspace;
1861f3c94560SMatthew G. Knepley   PetscReal      slope, intercept;
18627f96f943SMatthew G. Knepley   PetscBool      hasJac, hasPrec, isLin = PETSC_FALSE;
1863f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1864f017bcb6SMatthew G. Knepley 
1865f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1866f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1867f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1868f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
1869534a8f05SLisandro Dalcin   if (isLinear) PetscValidBoolPointer(isLinear, 5);
1870064a246eSJacob Faibussowitsch   if (convRate) PetscValidRealPointer(convRate, 6);
1871f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1872f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr);
1873f017bcb6SMatthew G. Knepley   /* Create and view matrices */
1874f017bcb6SMatthew G. Knepley   ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr);
18757f96f943SMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1876f017bcb6SMatthew G. Knepley   ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr);
1877f017bcb6SMatthew G. Knepley   ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr);
1878282e7bb4SMatthew G. Knepley   if (hasJac && hasPrec) {
1879282e7bb4SMatthew G. Knepley     ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr);
1880282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr);
1881f017bcb6SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) M, "Preconditioning Matrix");CHKERRQ(ierr);
1882282e7bb4SMatthew G. Knepley     ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr);
1883282e7bb4SMatthew G. Knepley     ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr);
1884282e7bb4SMatthew G. Knepley     ierr = MatDestroy(&M);CHKERRQ(ierr);
1885282e7bb4SMatthew G. Knepley   } else {
1886282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr);
1887282e7bb4SMatthew G. Knepley   }
1888f017bcb6SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) J, "Jacobian");CHKERRQ(ierr);
1889282e7bb4SMatthew G. Knepley   ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr);
1890282e7bb4SMatthew G. Knepley   ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr);
1891f017bcb6SMatthew G. Knepley   /* Check nullspace */
1892f017bcb6SMatthew G. Knepley   ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
1893f017bcb6SMatthew G. Knepley   if (nullspace) {
18941878804aSMatthew G. Knepley     PetscBool isNull;
1895f017bcb6SMatthew G. Knepley     ierr = MatNullSpaceTest(nullspace, J, &isNull);CHKERRQ(ierr);
18962c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!isNull,comm, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid.");
18971878804aSMatthew G. Knepley   }
1898f017bcb6SMatthew G. Knepley   /* Taylor test */
1899f017bcb6SMatthew G. Knepley   {
1900f017bcb6SMatthew G. Knepley     PetscRandom rand;
1901f017bcb6SMatthew G. Knepley     Vec         du, uhat, r, rhat, df;
1902f3c94560SMatthew G. Knepley     PetscReal   h;
1903f017bcb6SMatthew G. Knepley     PetscReal  *es, *hs, *errors;
1904f017bcb6SMatthew G. Knepley     PetscReal   hMax = 1.0, hMin = 1e-6, hMult = 0.1;
1905f017bcb6SMatthew G. Knepley     PetscInt    Nv, v;
1906f017bcb6SMatthew G. Knepley 
1907f017bcb6SMatthew G. Knepley     /* Choose a perturbation direction */
1908f017bcb6SMatthew G. Knepley     ierr = PetscRandomCreate(comm, &rand);CHKERRQ(ierr);
1909f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &du);CHKERRQ(ierr);
1910f017bcb6SMatthew G. Knepley     ierr = VecSetRandom(du, rand);CHKERRQ(ierr);
1911f017bcb6SMatthew G. Knepley     ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr);
1912f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &df);CHKERRQ(ierr);
1913f017bcb6SMatthew G. Knepley     ierr = MatMult(J, du, df);CHKERRQ(ierr);
1914f017bcb6SMatthew G. Knepley     /* Evaluate residual at u, F(u), save in vector r */
1915f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
1916f017bcb6SMatthew G. Knepley     ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr);
1917f017bcb6SMatthew G. Knepley     /* Look at the convergence of our Taylor approximation as we approach u */
1918f017bcb6SMatthew G. Knepley     for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv);
1919f017bcb6SMatthew G. Knepley     ierr = PetscCalloc3(Nv, &es, Nv, &hs, Nv, &errors);CHKERRQ(ierr);
1920f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &uhat);CHKERRQ(ierr);
1921f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &rhat);CHKERRQ(ierr);
1922f017bcb6SMatthew G. Knepley     for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv) {
1923f017bcb6SMatthew G. Knepley       ierr = VecWAXPY(uhat, h, du, u);CHKERRQ(ierr);
1924f017bcb6SMatthew G. Knepley       /* F(\hat u) \approx F(u) + J(u) (uhat - u) = F(u) + h * J(u) du */
1925f017bcb6SMatthew G. Knepley       ierr = SNESComputeFunction(snes, uhat, rhat);CHKERRQ(ierr);
1926f017bcb6SMatthew G. Knepley       ierr = VecAXPBYPCZ(rhat, -1.0, -h, 1.0, r, df);CHKERRQ(ierr);
1927f017bcb6SMatthew G. Knepley       ierr = VecNorm(rhat, NORM_2, &errors[Nv]);CHKERRQ(ierr);
1928f017bcb6SMatthew G. Knepley 
1929f017bcb6SMatthew G. Knepley       es[Nv] = PetscLog10Real(errors[Nv]);
1930f017bcb6SMatthew G. Knepley       hs[Nv] = PetscLog10Real(h);
1931f017bcb6SMatthew G. Knepley     }
1932f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&uhat);CHKERRQ(ierr);
1933f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&rhat);CHKERRQ(ierr);
1934f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&df);CHKERRQ(ierr);
19351878804aSMatthew G. Knepley     ierr = VecDestroy(&r);CHKERRQ(ierr);
1936f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&du);CHKERRQ(ierr);
1937f017bcb6SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
1938f017bcb6SMatthew G. Knepley       if ((tol >= 0) && (errors[v] > tol)) break;
1939f017bcb6SMatthew G. Knepley       else if (errors[v] > PETSC_SMALL)    break;
1940f017bcb6SMatthew G. Knepley     }
1941f3c94560SMatthew G. Knepley     if (v == Nv) isLin = PETSC_TRUE;
1942f017bcb6SMatthew G. Knepley     ierr = PetscLinearRegression(Nv, hs, es, &slope, &intercept);CHKERRQ(ierr);
1943f017bcb6SMatthew G. Knepley     ierr = PetscFree3(es, hs, errors);CHKERRQ(ierr);
1944f017bcb6SMatthew G. Knepley     /* Slope should be about 2 */
1945f017bcb6SMatthew G. Knepley     if (tol >= 0) {
19462c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!isLin && PetscAbsReal(2 - slope) > tol,comm, PETSC_ERR_ARG_WRONG, "Taylor approximation convergence rate should be 2, not %0.2f", (double) slope);
1947b878532fSMatthew G. Knepley     } else if (isLinear || convRate) {
1948b878532fSMatthew G. Knepley       if (isLinear) *isLinear = isLin;
1949b878532fSMatthew G. Knepley       if (convRate) *convRate = slope;
1950f017bcb6SMatthew G. Knepley     } else {
1951f3c94560SMatthew G. Knepley       if (!isLin) {ierr = PetscPrintf(comm, "Taylor approximation converging at order %3.2f\n", (double) slope);CHKERRQ(ierr);}
1952f017bcb6SMatthew G. Knepley       else        {ierr = PetscPrintf(comm, "Function appears to be linear\n");CHKERRQ(ierr);}
1953f017bcb6SMatthew G. Knepley     }
1954f017bcb6SMatthew G. Knepley   }
19551878804aSMatthew G. Knepley   ierr = MatDestroy(&J);CHKERRQ(ierr);
19561878804aSMatthew G. Knepley   PetscFunctionReturn(0);
19571878804aSMatthew G. Knepley }
19581878804aSMatthew G. Knepley 
19597f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheck_Internal(SNES snes, DM dm, Vec u)
1960f017bcb6SMatthew G. Knepley {
1961f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1962f017bcb6SMatthew G. Knepley 
1963f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1964f2cacb80SMatthew G. Knepley   ierr = DMSNESCheckDiscretization(snes, dm, 0.0, u, -1.0, NULL);CHKERRQ(ierr);
1965f3c94560SMatthew G. Knepley   ierr = DMSNESCheckResidual(snes, dm, u, -1.0, NULL);CHKERRQ(ierr);
1966f3c94560SMatthew G. Knepley   ierr = DMSNESCheckJacobian(snes, dm, u, -1.0, NULL, NULL);CHKERRQ(ierr);
1967f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1968f017bcb6SMatthew G. Knepley }
1969f017bcb6SMatthew G. Knepley 
1970bee9a294SMatthew G. Knepley /*@C
1971bee9a294SMatthew G. Knepley   DMSNESCheckFromOptions - Check the residual and Jacobian functions using the exact solution by outputting some diagnostic information
1972bee9a294SMatthew G. Knepley 
1973bee9a294SMatthew G. Knepley   Input Parameters:
1974bee9a294SMatthew G. Knepley + snes - the SNES object
19757f96f943SMatthew G. Knepley - u    - representative SNES vector
19767f96f943SMatthew G. Knepley 
19777f96f943SMatthew G. Knepley   Note: The user must call PetscDSSetExactSolution() beforehand
1978bee9a294SMatthew G. Knepley 
1979bee9a294SMatthew G. Knepley   Level: developer
1980bee9a294SMatthew G. Knepley @*/
19817f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u)
19821878804aSMatthew G. Knepley {
19831878804aSMatthew G. Knepley   DM             dm;
19841878804aSMatthew G. Knepley   Vec            sol;
19851878804aSMatthew G. Knepley   PetscBool      check;
19861878804aSMatthew G. Knepley   PetscErrorCode ierr;
19871878804aSMatthew G. Knepley 
19881878804aSMatthew G. Knepley   PetscFunctionBegin;
1989c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr);
19901878804aSMatthew G. Knepley   if (!check) PetscFunctionReturn(0);
19911878804aSMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
19921878804aSMatthew G. Knepley   ierr = VecDuplicate(u, &sol);CHKERRQ(ierr);
19931878804aSMatthew G. Knepley   ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr);
19947f96f943SMatthew G. Knepley   ierr = DMSNESCheck_Internal(snes, dm, sol);CHKERRQ(ierr);
19951878804aSMatthew G. Knepley   ierr = VecDestroy(&sol);CHKERRQ(ierr);
1996552f7358SJed Brown   PetscFunctionReturn(0);
1997552f7358SJed Brown }
1998