xref: /petsc/src/snes/utils/dmplexsnes.c (revision 9a2a23af32d69877c6775932bcfb789a84c58340)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I "petscdmplex.h" I*/
2af0996ceSBarry Smith #include <petsc/private/snesimpl.h>     /*I "petscsnes.h"   I*/
324cdb843SMatthew G. Knepley #include <petscds.h>
4a925c78cSMatthew G. Knepley #include <petscblaslapack.h>
5af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
6af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h>
7552f7358SJed Brown 
8649ef022SMatthew Knepley static void pressure_Private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
9649ef022SMatthew Knepley                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
10649ef022SMatthew Knepley                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
11649ef022SMatthew Knepley                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar p[])
12649ef022SMatthew Knepley {
13649ef022SMatthew Knepley   p[0] = u[uOff[1]];
14649ef022SMatthew Knepley }
15649ef022SMatthew Knepley 
16649ef022SMatthew Knepley /*
17649ef022SMatthew 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.
18649ef022SMatthew Knepley 
19649ef022SMatthew Knepley   Collective on SNES
20649ef022SMatthew Knepley 
21649ef022SMatthew Knepley   Input Parameters:
22649ef022SMatthew Knepley + snes      - The SNES
23649ef022SMatthew Knepley . pfield    - The field number for pressure
24649ef022SMatthew Knepley . nullspace - The pressure nullspace
25649ef022SMatthew Knepley . u         - The solution vector
26649ef022SMatthew Knepley - ctx       - An optional user context
27649ef022SMatthew Knepley 
28649ef022SMatthew Knepley   Output Parameter:
29649ef022SMatthew Knepley . u         - The solution with a continuum pressure integral of zero
30649ef022SMatthew Knepley 
31649ef022SMatthew Knepley   Notes:
32649ef022SMatthew 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.
33649ef022SMatthew Knepley 
34649ef022SMatthew Knepley   Level: developer
35649ef022SMatthew Knepley 
36649ef022SMatthew Knepley .seealso: SNESConvergedCorrectPressure()
37649ef022SMatthew Knepley */
38649ef022SMatthew Knepley static PetscErrorCode SNESCorrectDiscretePressure_Private(SNES snes, PetscInt pfield, MatNullSpace nullspace, Vec u, void *ctx)
39649ef022SMatthew Knepley {
40649ef022SMatthew Knepley   DM             dm;
41649ef022SMatthew Knepley   PetscDS        ds;
42649ef022SMatthew Knepley   const Vec     *nullvecs;
43649ef022SMatthew Knepley   PetscScalar    pintd, *intc, *intn;
44649ef022SMatthew Knepley   MPI_Comm       comm;
45649ef022SMatthew Knepley   PetscInt       Nf, Nv;
46649ef022SMatthew Knepley   PetscErrorCode ierr;
47649ef022SMatthew Knepley 
48649ef022SMatthew Knepley   PetscFunctionBegin;
49649ef022SMatthew Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
50649ef022SMatthew Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
51649ef022SMatthew Knepley   if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a SNES DM");
52649ef022SMatthew Knepley   if (!nullspace) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a Jacobian nullspace");
53649ef022SMatthew Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
54649ef022SMatthew Knepley   ierr = PetscDSSetObjective(ds, pfield, pressure_Private);CHKERRQ(ierr);
55649ef022SMatthew Knepley   ierr = MatNullSpaceGetVecs(nullspace, NULL, &Nv, &nullvecs);CHKERRQ(ierr);
56649ef022SMatthew Knepley   if (Nv != 1) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Can only handle a single null vector for pressure, not %D", Nv);
57649ef022SMatthew Knepley   ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr);
58649ef022SMatthew Knepley   if (PetscAbsScalar(pintd) > PETSC_SMALL) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd));
59649ef022SMatthew Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
60649ef022SMatthew Knepley   ierr = PetscMalloc2(Nf, &intc, Nf, &intn);CHKERRQ(ierr);
61649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, nullvecs[0], intn, ctx);CHKERRQ(ierr);
62649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr);
63649ef022SMatthew Knepley   ierr = VecAXPY(u, -intc[pfield]/intn[pfield], nullvecs[0]);CHKERRQ(ierr);
64649ef022SMatthew Knepley #if defined (PETSC_USE_DEBUG)
65649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr);
66649ef022SMatthew Knepley   if (PetscAbsScalar(intc[pfield]) > PETSC_SMALL) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Continuum integral of pressure after correction: %g\n", (double) PetscRealPart(intc[pfield]));
67649ef022SMatthew Knepley #endif
68649ef022SMatthew Knepley   ierr = PetscFree2(intc, intn);CHKERRQ(ierr);
69649ef022SMatthew Knepley   PetscFunctionReturn(0);
70649ef022SMatthew Knepley }
71649ef022SMatthew Knepley 
72649ef022SMatthew Knepley /*@C
73649ef022SMatthew 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().
74649ef022SMatthew Knepley 
75649ef022SMatthew Knepley    Logically Collective on SNES
76649ef022SMatthew Knepley 
77649ef022SMatthew Knepley    Input Parameters:
78649ef022SMatthew Knepley +  snes - the SNES context
79649ef022SMatthew Knepley .  it - the iteration (0 indicates before any Newton steps)
80649ef022SMatthew Knepley .  xnorm - 2-norm of current iterate
81649ef022SMatthew Knepley .  snorm - 2-norm of current step
82649ef022SMatthew Knepley .  fnorm - 2-norm of function at current iterate
83649ef022SMatthew Knepley -  ctx   - Optional user context
84649ef022SMatthew Knepley 
85649ef022SMatthew Knepley    Output Parameter:
86649ef022SMatthew Knepley .  reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
87649ef022SMatthew Knepley 
88649ef022SMatthew Knepley    Notes:
89649ef022SMatthew 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.
90649ef022SMatthew Knepley 
91649ef022SMatthew Knepley    Level: advanced
92649ef022SMatthew Knepley 
93649ef022SMatthew Knepley .seealso: SNESConvergedDefault(), SNESSetConvergenceTest(), DMSetNullSpaceConstructor()
94649ef022SMatthew Knepley @*/
95649ef022SMatthew Knepley PetscErrorCode SNESConvergedCorrectPressure(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *ctx)
96649ef022SMatthew Knepley {
97649ef022SMatthew Knepley   PetscBool      monitorIntegral = PETSC_FALSE;
98649ef022SMatthew Knepley   PetscErrorCode ierr;
99649ef022SMatthew Knepley 
100649ef022SMatthew Knepley   PetscFunctionBegin;
101649ef022SMatthew Knepley   ierr = SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx);CHKERRQ(ierr);
102649ef022SMatthew Knepley   if (monitorIntegral) {
103649ef022SMatthew Knepley     Mat          J;
104649ef022SMatthew Knepley     Vec          u;
105649ef022SMatthew Knepley     MatNullSpace nullspace;
106649ef022SMatthew Knepley     const Vec   *nullvecs;
107649ef022SMatthew Knepley     PetscScalar  pintd;
108649ef022SMatthew Knepley 
109649ef022SMatthew Knepley     ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr);
110649ef022SMatthew Knepley     ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr);
111649ef022SMatthew Knepley     ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
112649ef022SMatthew Knepley     ierr = MatNullSpaceGetVecs(nullspace, NULL, NULL, &nullvecs);CHKERRQ(ierr);
113649ef022SMatthew Knepley     ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr);
114649ef022SMatthew Knepley     ierr = PetscInfo1(snes, "SNES: Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd));CHKERRQ(ierr);
115649ef022SMatthew Knepley   }
116649ef022SMatthew Knepley   if (*reason > 0) {
117649ef022SMatthew Knepley     Mat          J;
118649ef022SMatthew Knepley     Vec          u;
119649ef022SMatthew Knepley     MatNullSpace nullspace;
120649ef022SMatthew Knepley     PetscInt     pfield = 1;
121649ef022SMatthew Knepley 
122649ef022SMatthew Knepley     ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr);
123649ef022SMatthew Knepley     ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr);
124649ef022SMatthew Knepley     ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
125649ef022SMatthew Knepley     ierr = SNESCorrectDiscretePressure_Private(snes, pfield, nullspace, u, ctx);CHKERRQ(ierr);
126649ef022SMatthew Knepley   }
127649ef022SMatthew Knepley   PetscFunctionReturn(0);
128649ef022SMatthew Knepley }
129649ef022SMatthew Knepley 
13024cdb843SMatthew G. Knepley /************************** Interpolation *******************************/
13124cdb843SMatthew G. Knepley 
1326da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy)
1336da023fcSToby Isaac {
1346da023fcSToby Isaac   PetscBool      isPlex;
1356da023fcSToby Isaac   PetscErrorCode ierr;
1366da023fcSToby Isaac 
1376da023fcSToby Isaac   PetscFunctionBegin;
1386da023fcSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr);
1396da023fcSToby Isaac   if (isPlex) {
1406da023fcSToby Isaac     *plex = dm;
1416da023fcSToby Isaac     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
142f7148743SMatthew G. Knepley   } else {
143f7148743SMatthew G. Knepley     ierr = PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex);CHKERRQ(ierr);
144f7148743SMatthew G. Knepley     if (!*plex) {
1456da023fcSToby Isaac       ierr = DMConvert(dm,DMPLEX,plex);CHKERRQ(ierr);
146f7148743SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex);CHKERRQ(ierr);
1476da023fcSToby Isaac       if (copy) {
1486da023fcSToby Isaac         ierr = DMCopyDMSNES(dm, *plex);CHKERRQ(ierr);
149*9a2a23afSMatthew G. Knepley         ierr = DMCopyAuxiliaryVec(dm, *plex);CHKERRQ(ierr);
1506da023fcSToby Isaac       }
151f7148743SMatthew G. Knepley     } else {
152f7148743SMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) *plex);CHKERRQ(ierr);
153f7148743SMatthew G. Knepley     }
1546da023fcSToby Isaac   }
1556da023fcSToby Isaac   PetscFunctionReturn(0);
1566da023fcSToby Isaac }
1576da023fcSToby Isaac 
1584267b1a3SMatthew G. Knepley /*@C
1594267b1a3SMatthew G. Knepley   DMInterpolationCreate - Creates a DMInterpolationInfo context
1604267b1a3SMatthew G. Knepley 
161d083f849SBarry Smith   Collective
1624267b1a3SMatthew G. Knepley 
1634267b1a3SMatthew G. Knepley   Input Parameter:
1644267b1a3SMatthew G. Knepley . comm - the communicator
1654267b1a3SMatthew G. Knepley 
1664267b1a3SMatthew G. Knepley   Output Parameter:
1674267b1a3SMatthew G. Knepley . ctx - the context
1684267b1a3SMatthew G. Knepley 
1694267b1a3SMatthew G. Knepley   Level: beginner
1704267b1a3SMatthew G. Knepley 
1714267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationDestroy()
1724267b1a3SMatthew G. Knepley @*/
1730adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx)
1740adebc6cSBarry Smith {
175552f7358SJed Brown   PetscErrorCode ierr;
176552f7358SJed Brown 
177552f7358SJed Brown   PetscFunctionBegin;
178552f7358SJed Brown   PetscValidPointer(ctx, 2);
17995dccacaSBarry Smith   ierr = PetscNew(ctx);CHKERRQ(ierr);
1801aa26658SKarl Rupp 
181552f7358SJed Brown   (*ctx)->comm   = comm;
182552f7358SJed Brown   (*ctx)->dim    = -1;
183552f7358SJed Brown   (*ctx)->nInput = 0;
1840298fd71SBarry Smith   (*ctx)->points = NULL;
1850298fd71SBarry Smith   (*ctx)->cells  = NULL;
186552f7358SJed Brown   (*ctx)->n      = -1;
1870298fd71SBarry Smith   (*ctx)->coords = NULL;
188552f7358SJed Brown   PetscFunctionReturn(0);
189552f7358SJed Brown }
190552f7358SJed Brown 
1914267b1a3SMatthew G. Knepley /*@C
1924267b1a3SMatthew G. Knepley   DMInterpolationSetDim - Sets the spatial dimension for the interpolation context
1934267b1a3SMatthew G. Knepley 
1944267b1a3SMatthew G. Knepley   Not collective
1954267b1a3SMatthew G. Knepley 
1964267b1a3SMatthew G. Knepley   Input Parameters:
1974267b1a3SMatthew G. Knepley + ctx - the context
1984267b1a3SMatthew G. Knepley - dim - the spatial dimension
1994267b1a3SMatthew G. Knepley 
2004267b1a3SMatthew G. Knepley   Level: intermediate
2014267b1a3SMatthew G. Knepley 
2024267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2034267b1a3SMatthew G. Knepley @*/
2040adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim)
2050adebc6cSBarry Smith {
206552f7358SJed Brown   PetscFunctionBegin;
207ff1e0c32SBarry Smith   if ((dim < 1) || (dim > 3)) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %D", dim);
208552f7358SJed Brown   ctx->dim = dim;
209552f7358SJed Brown   PetscFunctionReturn(0);
210552f7358SJed Brown }
211552f7358SJed Brown 
2124267b1a3SMatthew G. Knepley /*@C
2134267b1a3SMatthew G. Knepley   DMInterpolationGetDim - Gets the spatial dimension for the interpolation context
2144267b1a3SMatthew G. Knepley 
2154267b1a3SMatthew G. Knepley   Not collective
2164267b1a3SMatthew G. Knepley 
2174267b1a3SMatthew G. Knepley   Input Parameter:
2184267b1a3SMatthew G. Knepley . ctx - the context
2194267b1a3SMatthew G. Knepley 
2204267b1a3SMatthew G. Knepley   Output Parameter:
2214267b1a3SMatthew G. Knepley . dim - the spatial dimension
2224267b1a3SMatthew G. Knepley 
2234267b1a3SMatthew G. Knepley   Level: intermediate
2244267b1a3SMatthew G. Knepley 
2254267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2264267b1a3SMatthew G. Knepley @*/
2270adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim)
2280adebc6cSBarry Smith {
229552f7358SJed Brown   PetscFunctionBegin;
230552f7358SJed Brown   PetscValidIntPointer(dim, 2);
231552f7358SJed Brown   *dim = ctx->dim;
232552f7358SJed Brown   PetscFunctionReturn(0);
233552f7358SJed Brown }
234552f7358SJed Brown 
2354267b1a3SMatthew G. Knepley /*@C
2364267b1a3SMatthew G. Knepley   DMInterpolationSetDof - Sets the number of fields interpolated at a point for the interpolation context
2374267b1a3SMatthew G. Knepley 
2384267b1a3SMatthew G. Knepley   Not collective
2394267b1a3SMatthew G. Knepley 
2404267b1a3SMatthew G. Knepley   Input Parameters:
2414267b1a3SMatthew G. Knepley + ctx - the context
2424267b1a3SMatthew G. Knepley - dof - the number of fields
2434267b1a3SMatthew G. Knepley 
2444267b1a3SMatthew G. Knepley   Level: intermediate
2454267b1a3SMatthew G. Knepley 
2464267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2474267b1a3SMatthew G. Knepley @*/
2480adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof)
2490adebc6cSBarry Smith {
250552f7358SJed Brown   PetscFunctionBegin;
251ff1e0c32SBarry Smith   if (dof < 1) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %D", dof);
252552f7358SJed Brown   ctx->dof = dof;
253552f7358SJed Brown   PetscFunctionReturn(0);
254552f7358SJed Brown }
255552f7358SJed Brown 
2564267b1a3SMatthew G. Knepley /*@C
2574267b1a3SMatthew G. Knepley   DMInterpolationGetDof - Gets the number of fields interpolated at a point for the interpolation context
2584267b1a3SMatthew G. Knepley 
2594267b1a3SMatthew G. Knepley   Not collective
2604267b1a3SMatthew G. Knepley 
2614267b1a3SMatthew G. Knepley   Input Parameter:
2624267b1a3SMatthew G. Knepley . ctx - the context
2634267b1a3SMatthew G. Knepley 
2644267b1a3SMatthew G. Knepley   Output Parameter:
2654267b1a3SMatthew G. Knepley . dof - the number of fields
2664267b1a3SMatthew G. Knepley 
2674267b1a3SMatthew G. Knepley   Level: intermediate
2684267b1a3SMatthew G. Knepley 
2694267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2704267b1a3SMatthew G. Knepley @*/
2710adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof)
2720adebc6cSBarry Smith {
273552f7358SJed Brown   PetscFunctionBegin;
274552f7358SJed Brown   PetscValidIntPointer(dof, 2);
275552f7358SJed Brown   *dof = ctx->dof;
276552f7358SJed Brown   PetscFunctionReturn(0);
277552f7358SJed Brown }
278552f7358SJed Brown 
2794267b1a3SMatthew G. Knepley /*@C
2804267b1a3SMatthew G. Knepley   DMInterpolationAddPoints - Add points at which we will interpolate the fields
2814267b1a3SMatthew G. Knepley 
2824267b1a3SMatthew G. Knepley   Not collective
2834267b1a3SMatthew G. Knepley 
2844267b1a3SMatthew G. Knepley   Input Parameters:
2854267b1a3SMatthew G. Knepley + ctx    - the context
2864267b1a3SMatthew G. Knepley . n      - the number of points
2874267b1a3SMatthew G. Knepley - points - the coordinates for each point, an array of size n * dim
2884267b1a3SMatthew G. Knepley 
2894267b1a3SMatthew G. Knepley   Note: The coordinate information is copied.
2904267b1a3SMatthew G. Knepley 
2914267b1a3SMatthew G. Knepley   Level: intermediate
2924267b1a3SMatthew G. Knepley 
2934267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationCreate()
2944267b1a3SMatthew G. Knepley @*/
2950adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[])
2960adebc6cSBarry Smith {
297552f7358SJed Brown   PetscErrorCode ierr;
298552f7358SJed Brown 
299552f7358SJed Brown   PetscFunctionBegin;
3000adebc6cSBarry Smith   if (ctx->dim < 0) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
3010adebc6cSBarry Smith   if (ctx->points)  SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet");
302552f7358SJed Brown   ctx->nInput = n;
3031aa26658SKarl Rupp 
304785e854fSJed Brown   ierr = PetscMalloc1(n*ctx->dim, &ctx->points);CHKERRQ(ierr);
305580bdb30SBarry Smith   ierr = PetscArraycpy(ctx->points, points, n*ctx->dim);CHKERRQ(ierr);
306552f7358SJed Brown   PetscFunctionReturn(0);
307552f7358SJed Brown }
308552f7358SJed Brown 
3094267b1a3SMatthew G. Knepley /*@C
31052aa1562SMatthew G. Knepley   DMInterpolationSetUp - Compute spatial indices for point location during interpolation
3114267b1a3SMatthew G. Knepley 
3124267b1a3SMatthew G. Knepley   Collective on ctx
3134267b1a3SMatthew G. Knepley 
3144267b1a3SMatthew G. Knepley   Input Parameters:
3154267b1a3SMatthew G. Knepley + ctx - the context
3164267b1a3SMatthew G. Knepley . dm  - the DM for the function space used for interpolation
31752aa1562SMatthew G. Knepley . redundantPoints - If PETSC_TRUE, all processes are passing in the same array of points. Otherwise, points need to be communicated among processes.
3187deeda50SSatish Balay - ignoreOutsideDomain - If PETSC_TRUE, ignore points outside the domain, otherwise return an error
3194267b1a3SMatthew G. Knepley 
3204267b1a3SMatthew G. Knepley   Level: intermediate
3214267b1a3SMatthew G. Knepley 
3224267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
3234267b1a3SMatthew G. Knepley @*/
32452aa1562SMatthew G. Knepley PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints, PetscBool ignoreOutsideDomain)
3250adebc6cSBarry Smith {
326552f7358SJed Brown   MPI_Comm          comm = ctx->comm;
327552f7358SJed Brown   PetscScalar       *a;
328552f7358SJed Brown   PetscInt          p, q, i;
329552f7358SJed Brown   PetscMPIInt       rank, size;
330552f7358SJed Brown   PetscErrorCode    ierr;
331552f7358SJed Brown   Vec               pointVec;
3323a93e3b7SToby Isaac   PetscSF           cellSF;
333552f7358SJed Brown   PetscLayout       layout;
334552f7358SJed Brown   PetscReal         *globalPoints;
335cb313848SJed Brown   PetscScalar       *globalPointsScalar;
336552f7358SJed Brown   const PetscInt    *ranges;
337552f7358SJed Brown   PetscMPIInt       *counts, *displs;
3383a93e3b7SToby Isaac   const PetscSFNode *foundCells;
3393a93e3b7SToby Isaac   const PetscInt    *foundPoints;
340552f7358SJed Brown   PetscMPIInt       *foundProcs, *globalProcs;
3413a93e3b7SToby Isaac   PetscInt          n, N, numFound;
342552f7358SJed Brown 
34319436ca2SJed Brown   PetscFunctionBegin;
34419436ca2SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
345ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
346ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
3470adebc6cSBarry Smith   if (ctx->dim < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
34819436ca2SJed Brown   /* Locate points */
34919436ca2SJed Brown   n = ctx->nInput;
350552f7358SJed Brown   if (!redundantPoints) {
351552f7358SJed Brown     ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
352552f7358SJed Brown     ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
353552f7358SJed Brown     ierr = PetscLayoutSetLocalSize(layout, n);CHKERRQ(ierr);
354552f7358SJed Brown     ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
355552f7358SJed Brown     ierr = PetscLayoutGetSize(layout, &N);CHKERRQ(ierr);
356552f7358SJed Brown     /* Communicate all points to all processes */
357dcca6d9dSJed Brown     ierr = PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs);CHKERRQ(ierr);
358552f7358SJed Brown     ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
359552f7358SJed Brown     for (p = 0; p < size; ++p) {
360552f7358SJed Brown       counts[p] = (ranges[p+1] - ranges[p])*ctx->dim;
361552f7358SJed Brown       displs[p] = ranges[p]*ctx->dim;
362552f7358SJed Brown     }
363ffc4695bSBarry Smith     ierr = MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm);CHKERRMPI(ierr);
364552f7358SJed Brown   } else {
365552f7358SJed Brown     N = n;
366552f7358SJed Brown     globalPoints = ctx->points;
36738ea73c8SJed Brown     counts = displs = NULL;
36838ea73c8SJed Brown     layout = NULL;
369552f7358SJed Brown   }
370552f7358SJed Brown #if 0
371dcca6d9dSJed Brown   ierr = PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
37219436ca2SJed Brown   /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */
373552f7358SJed Brown #else
374cb313848SJed Brown #if defined(PETSC_USE_COMPLEX)
37546b3086cSToby Isaac   ierr = PetscMalloc1(N*ctx->dim,&globalPointsScalar);CHKERRQ(ierr);
37646b3086cSToby Isaac   for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i];
377cb313848SJed Brown #else
378cb313848SJed Brown   globalPointsScalar = globalPoints;
379cb313848SJed Brown #endif
38004706141SMatthew G Knepley   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec);CHKERRQ(ierr);
381dcca6d9dSJed Brown   ierr = PetscMalloc2(N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
3827b5f2079SMatthew G. Knepley   for (p = 0; p < N; ++p) {foundProcs[p] = size;}
3833a93e3b7SToby Isaac   cellSF = NULL;
3842d1fa6caSMatthew G. Knepley   ierr = DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF);CHKERRQ(ierr);
3853a93e3b7SToby Isaac   ierr = PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells);CHKERRQ(ierr);
386552f7358SJed Brown #endif
3873a93e3b7SToby Isaac   for (p = 0; p < numFound; ++p) {
3883a93e3b7SToby Isaac     if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank;
389552f7358SJed Brown   }
390552f7358SJed Brown   /* Let the lowest rank process own each point */
391b2566f29SBarry Smith   ierr   = MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm);CHKERRQ(ierr);
392552f7358SJed Brown   ctx->n = 0;
393552f7358SJed Brown   for (p = 0; p < N; ++p) {
39452aa1562SMatthew G. Knepley     if (globalProcs[p] == size) {
39552aa1562SMatthew G. Knepley       if (!ignoreOutsideDomain) SETERRQ4(comm, PETSC_ERR_PLIB, "Point %d: %g %g %g not located in mesh", p, (double)globalPoints[p*ctx->dim+0], (double)(ctx->dim > 1 ? globalPoints[p*ctx->dim+1] : 0.0), (double)(ctx->dim > 2 ? globalPoints[p*ctx->dim+2] : 0.0));
39652aa1562SMatthew G. Knepley       else if (!rank) ++ctx->n;
39752aa1562SMatthew G. Knepley     } else if (globalProcs[p] == rank) ++ctx->n;
398552f7358SJed Brown   }
399552f7358SJed Brown   /* Create coordinates vector and array of owned cells */
400785e854fSJed Brown   ierr = PetscMalloc1(ctx->n, &ctx->cells);CHKERRQ(ierr);
401552f7358SJed Brown   ierr = VecCreate(comm, &ctx->coords);CHKERRQ(ierr);
402552f7358SJed Brown   ierr = VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE);CHKERRQ(ierr);
403552f7358SJed Brown   ierr = VecSetBlockSize(ctx->coords, ctx->dim);CHKERRQ(ierr);
404c0dedaeaSBarry Smith   ierr = VecSetType(ctx->coords,VECSTANDARD);CHKERRQ(ierr);
405552f7358SJed Brown   ierr = VecGetArray(ctx->coords, &a);CHKERRQ(ierr);
406552f7358SJed Brown   for (p = 0, q = 0, i = 0; p < N; ++p) {
407552f7358SJed Brown     if (globalProcs[p] == rank) {
408552f7358SJed Brown       PetscInt d;
409552f7358SJed Brown 
4101aa26658SKarl Rupp       for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d];
411f317b747SMatthew G. Knepley       ctx->cells[q] = foundCells[q].index;
412f317b747SMatthew G. Knepley       ++q;
413552f7358SJed Brown     }
41452aa1562SMatthew G. Knepley     if (globalProcs[p] == size && !rank) {
41552aa1562SMatthew G. Knepley       PetscInt d;
41652aa1562SMatthew G. Knepley 
41752aa1562SMatthew G. Knepley       for (d = 0; d < ctx->dim; ++d, ++i) a[i] = 0.;
41852aa1562SMatthew G. Knepley       ctx->cells[q] = -1;
41952aa1562SMatthew G. Knepley       ++q;
42052aa1562SMatthew G. Knepley     }
421552f7358SJed Brown   }
422552f7358SJed Brown   ierr = VecRestoreArray(ctx->coords, &a);CHKERRQ(ierr);
423552f7358SJed Brown #if 0
424552f7358SJed Brown   ierr = PetscFree3(foundCells,foundProcs,globalProcs);CHKERRQ(ierr);
425552f7358SJed Brown #else
426552f7358SJed Brown   ierr = PetscFree2(foundProcs,globalProcs);CHKERRQ(ierr);
4273a93e3b7SToby Isaac   ierr = PetscSFDestroy(&cellSF);CHKERRQ(ierr);
428552f7358SJed Brown   ierr = VecDestroy(&pointVec);CHKERRQ(ierr);
429552f7358SJed Brown #endif
430cb313848SJed Brown   if ((void*)globalPointsScalar != (void*)globalPoints) {ierr = PetscFree(globalPointsScalar);CHKERRQ(ierr);}
431d343d804SMatthew G. Knepley   if (!redundantPoints) {ierr = PetscFree3(globalPoints,counts,displs);CHKERRQ(ierr);}
432552f7358SJed Brown   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
433552f7358SJed Brown   PetscFunctionReturn(0);
434552f7358SJed Brown }
435552f7358SJed Brown 
4364267b1a3SMatthew G. Knepley /*@C
4374267b1a3SMatthew G. Knepley   DMInterpolationGetCoordinates - Gets a Vec with the coordinates of each interpolation point
4384267b1a3SMatthew G. Knepley 
4394267b1a3SMatthew G. Knepley   Collective on ctx
4404267b1a3SMatthew G. Knepley 
4414267b1a3SMatthew G. Knepley   Input Parameter:
4424267b1a3SMatthew G. Knepley . ctx - the context
4434267b1a3SMatthew G. Knepley 
4444267b1a3SMatthew G. Knepley   Output Parameter:
4454267b1a3SMatthew G. Knepley . coordinates  - the coordinates of interpolation points
4464267b1a3SMatthew G. Knepley 
4474267b1a3SMatthew 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.
4484267b1a3SMatthew G. Knepley 
4494267b1a3SMatthew G. Knepley   Level: intermediate
4504267b1a3SMatthew G. Knepley 
4514267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
4524267b1a3SMatthew G. Knepley @*/
4530adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates)
4540adebc6cSBarry Smith {
455552f7358SJed Brown   PetscFunctionBegin;
456552f7358SJed Brown   PetscValidPointer(coordinates, 2);
4570adebc6cSBarry Smith   if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
458552f7358SJed Brown   *coordinates = ctx->coords;
459552f7358SJed Brown   PetscFunctionReturn(0);
460552f7358SJed Brown }
461552f7358SJed Brown 
4624267b1a3SMatthew G. Knepley /*@C
4634267b1a3SMatthew G. Knepley   DMInterpolationGetVector - Gets a Vec which can hold all the interpolated field values
4644267b1a3SMatthew G. Knepley 
4654267b1a3SMatthew G. Knepley   Collective on ctx
4664267b1a3SMatthew G. Knepley 
4674267b1a3SMatthew G. Knepley   Input Parameter:
4684267b1a3SMatthew G. Knepley . ctx - the context
4694267b1a3SMatthew G. Knepley 
4704267b1a3SMatthew G. Knepley   Output Parameter:
4714267b1a3SMatthew G. Knepley . v  - a vector capable of holding the interpolated field values
4724267b1a3SMatthew G. Knepley 
4734267b1a3SMatthew G. Knepley   Note: This vector should be returned using DMInterpolationRestoreVector().
4744267b1a3SMatthew G. Knepley 
4754267b1a3SMatthew G. Knepley   Level: intermediate
4764267b1a3SMatthew G. Knepley 
4774267b1a3SMatthew G. Knepley .seealso: DMInterpolationRestoreVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
4784267b1a3SMatthew G. Knepley @*/
4790adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v)
4800adebc6cSBarry Smith {
481552f7358SJed Brown   PetscErrorCode ierr;
482552f7358SJed Brown 
483552f7358SJed Brown   PetscFunctionBegin;
484552f7358SJed Brown   PetscValidPointer(v, 2);
4850adebc6cSBarry Smith   if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
486552f7358SJed Brown   ierr = VecCreate(ctx->comm, v);CHKERRQ(ierr);
487552f7358SJed Brown   ierr = VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE);CHKERRQ(ierr);
488552f7358SJed Brown   ierr = VecSetBlockSize(*v, ctx->dof);CHKERRQ(ierr);
489c0dedaeaSBarry Smith   ierr = VecSetType(*v,VECSTANDARD);CHKERRQ(ierr);
490552f7358SJed Brown   PetscFunctionReturn(0);
491552f7358SJed Brown }
492552f7358SJed Brown 
4934267b1a3SMatthew G. Knepley /*@C
4944267b1a3SMatthew G. Knepley   DMInterpolationRestoreVector - Returns a Vec which can hold all the interpolated field values
4954267b1a3SMatthew G. Knepley 
4964267b1a3SMatthew G. Knepley   Collective on ctx
4974267b1a3SMatthew G. Knepley 
4984267b1a3SMatthew G. Knepley   Input Parameters:
4994267b1a3SMatthew G. Knepley + ctx - the context
5004267b1a3SMatthew G. Knepley - v  - a vector capable of holding the interpolated field values
5014267b1a3SMatthew G. Knepley 
5024267b1a3SMatthew G. Knepley   Level: intermediate
5034267b1a3SMatthew G. Knepley 
5044267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
5054267b1a3SMatthew G. Knepley @*/
5060adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v)
5070adebc6cSBarry Smith {
508552f7358SJed Brown   PetscErrorCode ierr;
509552f7358SJed Brown 
510552f7358SJed Brown   PetscFunctionBegin;
511552f7358SJed Brown   PetscValidPointer(v, 2);
5120adebc6cSBarry Smith   if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
513552f7358SJed Brown   ierr = VecDestroy(v);CHKERRQ(ierr);
514552f7358SJed Brown   PetscFunctionReturn(0);
515552f7358SJed Brown }
516552f7358SJed Brown 
5177a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
518a6dfd86eSKarl Rupp {
519552f7358SJed Brown   PetscReal      *v0, *J, *invJ, detJ;
52056044e6dSMatthew G. Knepley   const PetscScalar *coords;
52156044e6dSMatthew G. Knepley   PetscScalar    *a;
522552f7358SJed Brown   PetscInt       p;
523552f7358SJed Brown   PetscErrorCode ierr;
524552f7358SJed Brown 
525552f7358SJed Brown   PetscFunctionBegin;
526dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
52756044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
528552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
529552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
530552f7358SJed Brown     PetscInt     c = ctx->cells[p];
531a1e44745SMatthew G. Knepley     PetscScalar *x = NULL;
532552f7358SJed Brown     PetscReal    xi[4];
533552f7358SJed Brown     PetscInt     d, f, comp;
534552f7358SJed Brown 
5358e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
536ff1e0c32SBarry Smith     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c);
5370298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
5381aa26658SKarl Rupp     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
5391aa26658SKarl Rupp 
540552f7358SJed Brown     for (d = 0; d < ctx->dim; ++d) {
541552f7358SJed Brown       xi[d] = 0.0;
5421aa26658SKarl 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]);
5431aa26658SKarl 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];
544552f7358SJed Brown     }
5450298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
546552f7358SJed Brown   }
547552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
54856044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
549552f7358SJed Brown   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
550552f7358SJed Brown   PetscFunctionReturn(0);
551552f7358SJed Brown }
552552f7358SJed Brown 
5537a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
5547a1931ceSMatthew G. Knepley {
5557a1931ceSMatthew G. Knepley   PetscReal      *v0, *J, *invJ, detJ;
55656044e6dSMatthew G. Knepley   const PetscScalar *coords;
55756044e6dSMatthew G. Knepley   PetscScalar    *a;
5587a1931ceSMatthew G. Knepley   PetscInt       p;
5597a1931ceSMatthew G. Knepley   PetscErrorCode ierr;
5607a1931ceSMatthew G. Knepley 
5617a1931ceSMatthew G. Knepley   PetscFunctionBegin;
562dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
56356044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
5647a1931ceSMatthew G. Knepley   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
5657a1931ceSMatthew G. Knepley   for (p = 0; p < ctx->n; ++p) {
5667a1931ceSMatthew G. Knepley     PetscInt       c = ctx->cells[p];
5677a1931ceSMatthew G. Knepley     const PetscInt order[3] = {2, 1, 3};
5682584bbe8SMatthew G. Knepley     PetscScalar   *x = NULL;
5697a1931ceSMatthew G. Knepley     PetscReal      xi[4];
5707a1931ceSMatthew G. Knepley     PetscInt       d, f, comp;
5717a1931ceSMatthew G. Knepley 
5728e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
573ff1e0c32SBarry Smith     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c);
5747a1931ceSMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
5757a1931ceSMatthew G. Knepley     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
5767a1931ceSMatthew G. Knepley 
5777a1931ceSMatthew G. Knepley     for (d = 0; d < ctx->dim; ++d) {
5787a1931ceSMatthew G. Knepley       xi[d] = 0.0;
5797a1931ceSMatthew 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]);
5807a1931ceSMatthew 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];
5817a1931ceSMatthew G. Knepley     }
5827a1931ceSMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
5837a1931ceSMatthew G. Knepley   }
5847a1931ceSMatthew G. Knepley   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
58556044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
5867a1931ceSMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
5877a1931ceSMatthew G. Knepley   PetscFunctionReturn(0);
5887a1931ceSMatthew G. Knepley }
5897a1931ceSMatthew G. Knepley 
5905820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
591552f7358SJed Brown {
592552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
593552f7358SJed Brown   const PetscScalar x0        = vertices[0];
594552f7358SJed Brown   const PetscScalar y0        = vertices[1];
595552f7358SJed Brown   const PetscScalar x1        = vertices[2];
596552f7358SJed Brown   const PetscScalar y1        = vertices[3];
597552f7358SJed Brown   const PetscScalar x2        = vertices[4];
598552f7358SJed Brown   const PetscScalar y2        = vertices[5];
599552f7358SJed Brown   const PetscScalar x3        = vertices[6];
600552f7358SJed Brown   const PetscScalar y3        = vertices[7];
601552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
602552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
603552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
604552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
605552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
606552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
60756044e6dSMatthew G. Knepley   const PetscScalar *ref;
60856044e6dSMatthew G. Knepley   PetscScalar       *real;
609552f7358SJed Brown   PetscErrorCode    ierr;
610552f7358SJed Brown 
611552f7358SJed Brown   PetscFunctionBegin;
61256044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
613552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
614552f7358SJed Brown   {
615552f7358SJed Brown     const PetscScalar p0 = ref[0];
616552f7358SJed Brown     const PetscScalar p1 = ref[1];
617552f7358SJed Brown 
618552f7358SJed Brown     real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1;
619552f7358SJed Brown     real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1;
620552f7358SJed Brown   }
621552f7358SJed Brown   ierr = PetscLogFlops(28);CHKERRQ(ierr);
62256044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
623552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
624552f7358SJed Brown   PetscFunctionReturn(0);
625552f7358SJed Brown }
626552f7358SJed Brown 
627af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
628d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
629552f7358SJed Brown {
630552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
631552f7358SJed Brown   const PetscScalar x0        = vertices[0];
632552f7358SJed Brown   const PetscScalar y0        = vertices[1];
633552f7358SJed Brown   const PetscScalar x1        = vertices[2];
634552f7358SJed Brown   const PetscScalar y1        = vertices[3];
635552f7358SJed Brown   const PetscScalar x2        = vertices[4];
636552f7358SJed Brown   const PetscScalar y2        = vertices[5];
637552f7358SJed Brown   const PetscScalar x3        = vertices[6];
638552f7358SJed Brown   const PetscScalar y3        = vertices[7];
639552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
640552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
64156044e6dSMatthew G. Knepley   const PetscScalar *ref;
642552f7358SJed Brown   PetscErrorCode    ierr;
643552f7358SJed Brown 
644552f7358SJed Brown   PetscFunctionBegin;
64556044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
646552f7358SJed Brown   {
647552f7358SJed Brown     const PetscScalar x       = ref[0];
648552f7358SJed Brown     const PetscScalar y       = ref[1];
649552f7358SJed Brown     const PetscInt    rows[2] = {0, 1};
650da80777bSKarl Rupp     PetscScalar       values[4];
651da80777bSKarl Rupp 
652da80777bSKarl Rupp     values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5;
653da80777bSKarl Rupp     values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5;
65494ab13aaSBarry Smith     ierr      = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr);
655552f7358SJed Brown   }
656552f7358SJed Brown   ierr = PetscLogFlops(30);CHKERRQ(ierr);
65756044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
65894ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65994ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
660552f7358SJed Brown   PetscFunctionReturn(0);
661552f7358SJed Brown }
662552f7358SJed Brown 
663a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
664a6dfd86eSKarl Rupp {
665fafc0619SMatthew G Knepley   DM             dmCoord;
666de73a395SMatthew G. Knepley   PetscFE        fem = NULL;
667552f7358SJed Brown   SNES           snes;
668552f7358SJed Brown   KSP            ksp;
669552f7358SJed Brown   PC             pc;
670552f7358SJed Brown   Vec            coordsLocal, r, ref, real;
671552f7358SJed Brown   Mat            J;
672ef0bb6c7SMatthew G. Knepley   PetscTabulation    T;
67356044e6dSMatthew G. Knepley   const PetscScalar *coords;
67456044e6dSMatthew G. Knepley   PetscScalar    *a;
675ef0bb6c7SMatthew G. Knepley   PetscReal      xir[2];
676de73a395SMatthew G. Knepley   PetscInt       Nf, p;
6775509d985SMatthew G. Knepley   const PetscInt dof = ctx->dof;
678552f7358SJed Brown   PetscErrorCode ierr;
679552f7358SJed Brown 
680552f7358SJed Brown   PetscFunctionBegin;
681de73a395SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
68244a7f3ddSMatthew G. Knepley   if (Nf) {ierr = DMGetField(dm, 0, NULL, (PetscObject *) &fem);CHKERRQ(ierr);}
683552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
684fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
685552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
686552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr);
687552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
688552f7358SJed Brown   ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr);
689c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
690552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
691552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
692552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
693552f7358SJed Brown   ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr);
694552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
695552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
6960298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr);
6970298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr);
698552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
699552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
700552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
701552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
702552f7358SJed Brown 
70356044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
704552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
705ef0bb6c7SMatthew G. Knepley   ierr = PetscFECreateTabulation(fem, 1, 1, xir, 0, &T);CHKERRQ(ierr);
706552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
707a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
708552f7358SJed Brown     PetscScalar *xi;
709552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
710552f7358SJed Brown 
711552f7358SJed Brown     /* Can make this do all points at once */
7120298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
713ff1e0c32SBarry Smith     if (4*2 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 4*2);
7140298fd71SBarry Smith     ierr   = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
7150298fd71SBarry Smith     ierr   = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
7160298fd71SBarry Smith     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
717552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
718552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
719552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
720552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
721552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
722552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
723cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
724cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
7255509d985SMatthew G. Knepley     if (4*dof != xSize) {
7265509d985SMatthew G. Knepley       PetscInt d;
7271aa26658SKarl Rupp 
7285509d985SMatthew G. Knepley       xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0;
729ef0bb6c7SMatthew G. Knepley       ierr = PetscFEComputeTabulation(fem, 1, xir, 0, T);CHKERRQ(ierr);
7305509d985SMatthew G. Knepley       for (comp = 0; comp < dof; ++comp) {
7315509d985SMatthew G. Knepley         a[p*dof+comp] = 0.0;
7325509d985SMatthew G. Knepley         for (d = 0; d < xSize/dof; ++d) {
733ef0bb6c7SMatthew G. Knepley           a[p*dof+comp] += x[d*dof+comp]*T->T[0][d*dof+comp];
7345509d985SMatthew G. Knepley         }
7355509d985SMatthew G. Knepley       }
7365509d985SMatthew G. Knepley     } else {
7375509d985SMatthew G. Knepley       for (comp = 0; comp < dof; ++comp)
7385509d985SMatthew 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];
7395509d985SMatthew G. Knepley     }
740552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
7410298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
7420298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
743552f7358SJed Brown   }
744ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr);
745552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
74656044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
747552f7358SJed Brown 
748552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
749552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
750552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
751552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
752552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
753552f7358SJed Brown   PetscFunctionReturn(0);
754552f7358SJed Brown }
755552f7358SJed Brown 
7565820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
757552f7358SJed Brown {
758552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
759552f7358SJed Brown   const PetscScalar x0        = vertices[0];
760552f7358SJed Brown   const PetscScalar y0        = vertices[1];
761552f7358SJed Brown   const PetscScalar z0        = vertices[2];
7627a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
7637a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
7647a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
765552f7358SJed Brown   const PetscScalar x2        = vertices[6];
766552f7358SJed Brown   const PetscScalar y2        = vertices[7];
767552f7358SJed Brown   const PetscScalar z2        = vertices[8];
7687a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
7697a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
7707a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
771552f7358SJed Brown   const PetscScalar x4        = vertices[12];
772552f7358SJed Brown   const PetscScalar y4        = vertices[13];
773552f7358SJed Brown   const PetscScalar z4        = vertices[14];
774552f7358SJed Brown   const PetscScalar x5        = vertices[15];
775552f7358SJed Brown   const PetscScalar y5        = vertices[16];
776552f7358SJed Brown   const PetscScalar z5        = vertices[17];
777552f7358SJed Brown   const PetscScalar x6        = vertices[18];
778552f7358SJed Brown   const PetscScalar y6        = vertices[19];
779552f7358SJed Brown   const PetscScalar z6        = vertices[20];
780552f7358SJed Brown   const PetscScalar x7        = vertices[21];
781552f7358SJed Brown   const PetscScalar y7        = vertices[22];
782552f7358SJed Brown   const PetscScalar z7        = vertices[23];
783552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
784552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
785552f7358SJed Brown   const PetscScalar h_1       = z1 - z0;
786552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
787552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
788552f7358SJed Brown   const PetscScalar h_3       = z3 - z0;
789552f7358SJed Brown   const PetscScalar f_4       = x4 - x0;
790552f7358SJed Brown   const PetscScalar g_4       = y4 - y0;
791552f7358SJed Brown   const PetscScalar h_4       = z4 - z0;
792552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
793552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
794552f7358SJed Brown   const PetscScalar h_01      = z2 - z1 - z3 + z0;
795552f7358SJed Brown   const PetscScalar f_12      = x7 - x3 - x4 + x0;
796552f7358SJed Brown   const PetscScalar g_12      = y7 - y3 - y4 + y0;
797552f7358SJed Brown   const PetscScalar h_12      = z7 - z3 - z4 + z0;
798552f7358SJed Brown   const PetscScalar f_02      = x5 - x1 - x4 + x0;
799552f7358SJed Brown   const PetscScalar g_02      = y5 - y1 - y4 + y0;
800552f7358SJed Brown   const PetscScalar h_02      = z5 - z1 - z4 + z0;
801552f7358SJed Brown   const PetscScalar f_012     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
802552f7358SJed Brown   const PetscScalar g_012     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
803552f7358SJed Brown   const PetscScalar h_012     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
80456044e6dSMatthew G. Knepley   const PetscScalar *ref;
80556044e6dSMatthew G. Knepley   PetscScalar       *real;
806552f7358SJed Brown   PetscErrorCode    ierr;
807552f7358SJed Brown 
808552f7358SJed Brown   PetscFunctionBegin;
80956044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
810552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
811552f7358SJed Brown   {
812552f7358SJed Brown     const PetscScalar p0 = ref[0];
813552f7358SJed Brown     const PetscScalar p1 = ref[1];
814552f7358SJed Brown     const PetscScalar p2 = ref[2];
815552f7358SJed Brown 
816552f7358SJed 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;
817552f7358SJed 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;
818552f7358SJed 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;
819552f7358SJed Brown   }
820552f7358SJed Brown   ierr = PetscLogFlops(114);CHKERRQ(ierr);
82156044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
822552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
823552f7358SJed Brown   PetscFunctionReturn(0);
824552f7358SJed Brown }
825552f7358SJed Brown 
826d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
827552f7358SJed Brown {
828552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
829552f7358SJed Brown   const PetscScalar x0        = vertices[0];
830552f7358SJed Brown   const PetscScalar y0        = vertices[1];
831552f7358SJed Brown   const PetscScalar z0        = vertices[2];
8327a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
8337a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
8347a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
835552f7358SJed Brown   const PetscScalar x2        = vertices[6];
836552f7358SJed Brown   const PetscScalar y2        = vertices[7];
837552f7358SJed Brown   const PetscScalar z2        = vertices[8];
8387a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
8397a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
8407a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
841552f7358SJed Brown   const PetscScalar x4        = vertices[12];
842552f7358SJed Brown   const PetscScalar y4        = vertices[13];
843552f7358SJed Brown   const PetscScalar z4        = vertices[14];
844552f7358SJed Brown   const PetscScalar x5        = vertices[15];
845552f7358SJed Brown   const PetscScalar y5        = vertices[16];
846552f7358SJed Brown   const PetscScalar z5        = vertices[17];
847552f7358SJed Brown   const PetscScalar x6        = vertices[18];
848552f7358SJed Brown   const PetscScalar y6        = vertices[19];
849552f7358SJed Brown   const PetscScalar z6        = vertices[20];
850552f7358SJed Brown   const PetscScalar x7        = vertices[21];
851552f7358SJed Brown   const PetscScalar y7        = vertices[22];
852552f7358SJed Brown   const PetscScalar z7        = vertices[23];
853552f7358SJed Brown   const PetscScalar f_xy      = x2 - x1 - x3 + x0;
854552f7358SJed Brown   const PetscScalar g_xy      = y2 - y1 - y3 + y0;
855552f7358SJed Brown   const PetscScalar h_xy      = z2 - z1 - z3 + z0;
856552f7358SJed Brown   const PetscScalar f_yz      = x7 - x3 - x4 + x0;
857552f7358SJed Brown   const PetscScalar g_yz      = y7 - y3 - y4 + y0;
858552f7358SJed Brown   const PetscScalar h_yz      = z7 - z3 - z4 + z0;
859552f7358SJed Brown   const PetscScalar f_xz      = x5 - x1 - x4 + x0;
860552f7358SJed Brown   const PetscScalar g_xz      = y5 - y1 - y4 + y0;
861552f7358SJed Brown   const PetscScalar h_xz      = z5 - z1 - z4 + z0;
862552f7358SJed Brown   const PetscScalar f_xyz     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
863552f7358SJed Brown   const PetscScalar g_xyz     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
864552f7358SJed Brown   const PetscScalar h_xyz     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
86556044e6dSMatthew G. Knepley   const PetscScalar *ref;
866552f7358SJed Brown   PetscErrorCode    ierr;
867552f7358SJed Brown 
868552f7358SJed Brown   PetscFunctionBegin;
86956044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
870552f7358SJed Brown   {
871552f7358SJed Brown     const PetscScalar x       = ref[0];
872552f7358SJed Brown     const PetscScalar y       = ref[1];
873552f7358SJed Brown     const PetscScalar z       = ref[2];
874552f7358SJed Brown     const PetscInt    rows[3] = {0, 1, 2};
875da80777bSKarl Rupp     PetscScalar       values[9];
876da80777bSKarl Rupp 
877da80777bSKarl Rupp     values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0;
878da80777bSKarl Rupp     values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0;
879da80777bSKarl Rupp     values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0;
880da80777bSKarl Rupp     values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0;
881da80777bSKarl Rupp     values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0;
882da80777bSKarl Rupp     values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0;
883da80777bSKarl Rupp     values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0;
884da80777bSKarl Rupp     values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0;
885da80777bSKarl Rupp     values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0;
8861aa26658SKarl Rupp 
88794ab13aaSBarry Smith     ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr);
888552f7358SJed Brown   }
889552f7358SJed Brown   ierr = PetscLogFlops(152);CHKERRQ(ierr);
89056044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
89194ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
89294ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
893552f7358SJed Brown   PetscFunctionReturn(0);
894552f7358SJed Brown }
895552f7358SJed Brown 
896a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
897a6dfd86eSKarl Rupp {
898fafc0619SMatthew G Knepley   DM             dmCoord;
899552f7358SJed Brown   SNES           snes;
900552f7358SJed Brown   KSP            ksp;
901552f7358SJed Brown   PC             pc;
902552f7358SJed Brown   Vec            coordsLocal, r, ref, real;
903552f7358SJed Brown   Mat            J;
90456044e6dSMatthew G. Knepley   const PetscScalar *coords;
90556044e6dSMatthew G. Knepley   PetscScalar    *a;
906552f7358SJed Brown   PetscInt       p;
907552f7358SJed Brown   PetscErrorCode ierr;
908552f7358SJed Brown 
909552f7358SJed Brown   PetscFunctionBegin;
910552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
911fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
912552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
913552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr);
914552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
915552f7358SJed Brown   ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr);
916c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
917552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
918552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
919552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
920552f7358SJed Brown   ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr);
921552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
922552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
9230298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr);
9240298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr);
925552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
926552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
927552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
928552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
929552f7358SJed Brown 
93056044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
931552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
932552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
933a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
934552f7358SJed Brown     PetscScalar *xi;
935cb313848SJed Brown     PetscReal    xir[3];
936552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
937552f7358SJed Brown 
938552f7358SJed Brown     /* Can make this do all points at once */
9390298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
940ff1e0c32SBarry Smith     if (8*3 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 8*3);
9410298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
942ff1e0c32SBarry Smith     if (8*ctx->dof != xSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %D", xSize, 8*ctx->dof);
9430298fd71SBarry Smith     ierr   = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
9440298fd71SBarry Smith     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr);
945552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
946552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
947552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
948552f7358SJed Brown     xi[2]  = coords[p*ctx->dim+2];
949552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
950552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
951552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
952cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
953cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
954cb313848SJed Brown     xir[2] = PetscRealPart(xi[2]);
955552f7358SJed Brown     for (comp = 0; comp < ctx->dof; ++comp) {
956552f7358SJed Brown       a[p*ctx->dof+comp] =
957cb313848SJed Brown         x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) +
9587a1931ceSMatthew G. Knepley         x[3*ctx->dof+comp]*    xir[0]*(1-xir[1])*(1-xir[2]) +
959cb313848SJed Brown         x[2*ctx->dof+comp]*    xir[0]*    xir[1]*(1-xir[2]) +
9607a1931ceSMatthew G. Knepley         x[1*ctx->dof+comp]*(1-xir[0])*    xir[1]*(1-xir[2]) +
961cb313848SJed Brown         x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*   xir[2] +
962cb313848SJed Brown         x[5*ctx->dof+comp]*    xir[0]*(1-xir[1])*   xir[2] +
963cb313848SJed Brown         x[6*ctx->dof+comp]*    xir[0]*    xir[1]*   xir[2] +
964cb313848SJed Brown         x[7*ctx->dof+comp]*(1-xir[0])*    xir[1]*   xir[2];
965552f7358SJed Brown     }
966552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
9670298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
9680298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
969552f7358SJed Brown   }
970552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
97156044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
972552f7358SJed Brown 
973552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
974552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
975552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
976552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
977552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
978552f7358SJed Brown   PetscFunctionReturn(0);
979552f7358SJed Brown }
980552f7358SJed Brown 
9814267b1a3SMatthew G. Knepley /*@C
9824267b1a3SMatthew G. Knepley   DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points.
9834267b1a3SMatthew G. Knepley 
984552f7358SJed Brown   Input Parameters:
985552f7358SJed Brown + ctx - The DMInterpolationInfo context
986552f7358SJed Brown . dm  - The DM
987552f7358SJed Brown - x   - The local vector containing the field to be interpolated
988552f7358SJed Brown 
989552f7358SJed Brown   Output Parameters:
990552f7358SJed Brown . v   - The vector containing the interpolated values
9914267b1a3SMatthew G. Knepley 
9924267b1a3SMatthew G. Knepley   Note: A suitable v can be obtained using DMInterpolationGetVector().
9934267b1a3SMatthew G. Knepley 
9944267b1a3SMatthew G. Knepley   Level: beginner
9954267b1a3SMatthew G. Knepley 
9964267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationAddPoints(), DMInterpolationCreate()
9974267b1a3SMatthew G. Knepley @*/
9980adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v)
9990adebc6cSBarry Smith {
1000680d18d5SMatthew G. Knepley   PetscInt       n;
1001552f7358SJed Brown   PetscErrorCode ierr;
1002552f7358SJed Brown 
1003552f7358SJed Brown   PetscFunctionBegin;
1004552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1005552f7358SJed Brown   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
1006552f7358SJed Brown   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
1007552f7358SJed Brown   ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
1008ff1e0c32SBarry Smith   if (n != ctx->n*ctx->dof) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %D should be %D", n, ctx->n*ctx->dof);
1009552f7358SJed Brown   if (n) {
1010680d18d5SMatthew G. Knepley     PetscDS        ds;
1011680d18d5SMatthew G. Knepley     DMPolytopeType ct;
1012680d18d5SMatthew G. Knepley     PetscBool      done = PETSC_FALSE;
1013680d18d5SMatthew G. Knepley 
1014680d18d5SMatthew G. Knepley     ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1015680d18d5SMatthew G. Knepley     if (ds) {
1016680d18d5SMatthew G. Knepley       const PetscScalar *coords;
1017680d18d5SMatthew G. Knepley       PetscScalar       *interpolant;
1018680d18d5SMatthew G. Knepley       PetscInt           cdim, d, p, Nf, field, c = 0;
1019680d18d5SMatthew G. Knepley 
1020680d18d5SMatthew G. Knepley       ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
1021680d18d5SMatthew G. Knepley       ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
1022680d18d5SMatthew G. Knepley       for (field = 0; field < Nf; ++field) {
1023680d18d5SMatthew G. Knepley         PetscTabulation T;
1024680d18d5SMatthew G. Knepley         PetscFE         fe;
1025680d18d5SMatthew G. Knepley         PetscClassId    id;
1026680d18d5SMatthew G. Knepley         PetscReal       xi[3];
1027680d18d5SMatthew G. Knepley         PetscInt        Nc, f, fc;
1028680d18d5SMatthew G. Knepley 
1029680d18d5SMatthew G. Knepley         ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
1030680d18d5SMatthew G. Knepley         ierr = PetscObjectGetClassId((PetscObject) fe, &id);CHKERRQ(ierr);
1031680d18d5SMatthew G. Knepley         if (id != PETSCFE_CLASSID) break;
1032680d18d5SMatthew G. Knepley         ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
1033680d18d5SMatthew G. Knepley         ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
1034680d18d5SMatthew G. Knepley         ierr = VecGetArrayWrite(v, &interpolant);CHKERRQ(ierr);
1035680d18d5SMatthew G. Knepley         for (p = 0; p < ctx->n; ++p) {
1036680d18d5SMatthew G. Knepley           PetscScalar *xa = NULL;
1037680d18d5SMatthew G. Knepley           PetscReal    pcoords[3];
1038680d18d5SMatthew G. Knepley 
103952aa1562SMatthew G. Knepley           if (ctx->cells[p] < 0) continue;
1040680d18d5SMatthew G. Knepley           for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p*cdim+d]);
1041680d18d5SMatthew G. Knepley           ierr = DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi);CHKERRQ(ierr);
1042680d18d5SMatthew G. Knepley           ierr = DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], NULL, &xa);CHKERRQ(ierr);
1043680d18d5SMatthew G. Knepley           ierr = PetscFECreateTabulation(fe, 1, 1, xi, 0, &T);CHKERRQ(ierr);
1044680d18d5SMatthew G. Knepley           {
1045680d18d5SMatthew G. Knepley             const PetscReal *basis = T->T[0];
1046680d18d5SMatthew G. Knepley             const PetscInt   Nb    = T->Nb;
1047680d18d5SMatthew G. Knepley             const PetscInt   Nc    = T->Nc;
1048680d18d5SMatthew G. Knepley             for (fc = 0; fc < Nc; ++fc) {
1049680d18d5SMatthew G. Knepley               interpolant[p*ctx->dof+c+fc] = 0.0;
1050680d18d5SMatthew G. Knepley               for (f = 0; f < Nb; ++f) {
1051680d18d5SMatthew G. Knepley                 interpolant[p*ctx->dof+c+fc] += xa[f]*basis[(0*Nb + f)*Nc + fc];
1052552f7358SJed Brown               }
1053680d18d5SMatthew G. Knepley             }
1054680d18d5SMatthew G. Knepley           }
1055680d18d5SMatthew G. Knepley           ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr);
1056680d18d5SMatthew G. Knepley           ierr = DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], NULL, &xa);CHKERRQ(ierr);
1057680d18d5SMatthew G. Knepley         }
1058680d18d5SMatthew G. Knepley         ierr = VecRestoreArrayWrite(v, &interpolant);CHKERRQ(ierr);
1059680d18d5SMatthew G. Knepley         ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
1060680d18d5SMatthew G. Knepley         c += Nc;
1061680d18d5SMatthew G. Knepley       }
1062680d18d5SMatthew G. Knepley       if (field == Nf) {
1063680d18d5SMatthew G. Knepley         done = PETSC_TRUE;
1064680d18d5SMatthew G. Knepley         if (c != ctx->dof) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %D != %D dof specified for interpolation", c, ctx->dof);
1065680d18d5SMatthew G. Knepley       }
1066680d18d5SMatthew G. Knepley     }
1067680d18d5SMatthew G. Knepley     if (!done) {
1068680d18d5SMatthew G. Knepley       /* TODO Check each cell individually */
1069680d18d5SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, ctx->cells[0], &ct);CHKERRQ(ierr);
1070680d18d5SMatthew G. Knepley       switch (ct) {
1071680d18d5SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:      ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1072680d18d5SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL: ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1073680d18d5SMatthew G. Knepley         case DM_POLYTOPE_TETRAHEDRON:   ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1074680d18d5SMatthew G. Knepley         case DM_POLYTOPE_HEXAHEDRON:    ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1075680d18d5SMatthew G. Knepley         default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support fpr cell type %s", DMPolytopeTypes[ct]);
1076680d18d5SMatthew G. Knepley       }
1077680d18d5SMatthew G. Knepley     }
1078552f7358SJed Brown   }
1079552f7358SJed Brown   PetscFunctionReturn(0);
1080552f7358SJed Brown }
1081552f7358SJed Brown 
10824267b1a3SMatthew G. Knepley /*@C
10834267b1a3SMatthew G. Knepley   DMInterpolationDestroy - Destroys a DMInterpolationInfo context
10844267b1a3SMatthew G. Knepley 
10854267b1a3SMatthew G. Knepley   Collective on ctx
10864267b1a3SMatthew G. Knepley 
10874267b1a3SMatthew G. Knepley   Input Parameter:
10884267b1a3SMatthew G. Knepley . ctx - the context
10894267b1a3SMatthew G. Knepley 
10904267b1a3SMatthew G. Knepley   Level: beginner
10914267b1a3SMatthew G. Knepley 
10924267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
10934267b1a3SMatthew G. Knepley @*/
10940adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx)
10950adebc6cSBarry Smith {
1096552f7358SJed Brown   PetscErrorCode ierr;
1097552f7358SJed Brown 
1098552f7358SJed Brown   PetscFunctionBegin;
1099552f7358SJed Brown   PetscValidPointer(ctx, 2);
1100552f7358SJed Brown   ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr);
1101552f7358SJed Brown   ierr = PetscFree((*ctx)->points);CHKERRQ(ierr);
1102552f7358SJed Brown   ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr);
1103552f7358SJed Brown   ierr = PetscFree(*ctx);CHKERRQ(ierr);
11040298fd71SBarry Smith   *ctx = NULL;
1105552f7358SJed Brown   PetscFunctionReturn(0);
1106552f7358SJed Brown }
1107cc0c4584SMatthew G. Knepley 
1108cc0c4584SMatthew G. Knepley /*@C
1109cc0c4584SMatthew G. Knepley   SNESMonitorFields - Monitors the residual for each field separately
1110cc0c4584SMatthew G. Knepley 
1111cc0c4584SMatthew G. Knepley   Collective on SNES
1112cc0c4584SMatthew G. Knepley 
1113cc0c4584SMatthew G. Knepley   Input Parameters:
1114cc0c4584SMatthew G. Knepley + snes   - the SNES context
1115cc0c4584SMatthew G. Knepley . its    - iteration number
1116cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual
1117d43b4f6eSBarry Smith - vf  - PetscViewerAndFormat of type ASCII
1118cc0c4584SMatthew G. Knepley 
1119cc0c4584SMatthew G. Knepley   Notes:
1120cc0c4584SMatthew G. Knepley   This routine prints the residual norm at each iteration.
1121cc0c4584SMatthew G. Knepley 
1122cc0c4584SMatthew G. Knepley   Level: intermediate
1123cc0c4584SMatthew G. Knepley 
1124cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault()
1125cc0c4584SMatthew G. Knepley @*/
1126d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
1127cc0c4584SMatthew G. Knepley {
1128d43b4f6eSBarry Smith   PetscViewer        viewer = vf->viewer;
1129cc0c4584SMatthew G. Knepley   Vec                res;
1130cc0c4584SMatthew G. Knepley   DM                 dm;
1131cc0c4584SMatthew G. Knepley   PetscSection       s;
1132cc0c4584SMatthew G. Knepley   const PetscScalar *r;
1133cc0c4584SMatthew G. Knepley   PetscReal         *lnorms, *norms;
1134cc0c4584SMatthew G. Knepley   PetscInt           numFields, f, pStart, pEnd, p;
1135cc0c4584SMatthew G. Knepley   PetscErrorCode     ierr;
1136cc0c4584SMatthew G. Knepley 
1137cc0c4584SMatthew G. Knepley   PetscFunctionBegin;
11384d4332d5SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
11399e5d0892SLisandro Dalcin   ierr = SNESGetFunction(snes, &res, NULL, NULL);CHKERRQ(ierr);
1140cc0c4584SMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
114192fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
1142cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr);
1143cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1144cc0c4584SMatthew G. Knepley   ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr);
1145cc0c4584SMatthew G. Knepley   ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr);
1146cc0c4584SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
1147cc0c4584SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
1148cc0c4584SMatthew G. Knepley       PetscInt fdof, foff, d;
1149cc0c4584SMatthew G. Knepley 
1150cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr);
1151cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr);
1152cc0c4584SMatthew G. Knepley       for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d]));
1153cc0c4584SMatthew G. Knepley     }
1154cc0c4584SMatthew G. Knepley   }
1155cc0c4584SMatthew G. Knepley   ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr);
1156b2566f29SBarry Smith   ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);
1157d43b4f6eSBarry Smith   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
1158cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
1159cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr);
1160cc0c4584SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
1161cc0c4584SMatthew G. Knepley     if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
1162cc0c4584SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr);
1163cc0c4584SMatthew G. Knepley   }
1164cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr);
1165cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
1166d43b4f6eSBarry Smith   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1167cc0c4584SMatthew G. Knepley   ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr);
1168cc0c4584SMatthew G. Knepley   PetscFunctionReturn(0);
1169cc0c4584SMatthew G. Knepley }
117024cdb843SMatthew G. Knepley 
117124cdb843SMatthew G. Knepley /********************* Residual Computation **************************/
117224cdb843SMatthew G. Knepley 
11736528b96dSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
11746528b96dSMatthew G. Knepley {
11756528b96dSMatthew G. Knepley   PetscInt       depth;
11766528b96dSMatthew G. Knepley   PetscErrorCode ierr;
11776528b96dSMatthew G. Knepley 
11786528b96dSMatthew G. Knepley   PetscFunctionBegin;
11796528b96dSMatthew G. Knepley   ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
11806528b96dSMatthew G. Knepley   ierr = DMGetStratumIS(plex, "dim", depth, cellIS);CHKERRQ(ierr);
11816528b96dSMatthew G. Knepley   if (!*cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, cellIS);CHKERRQ(ierr);}
11826528b96dSMatthew G. Knepley   PetscFunctionReturn(0);
11836528b96dSMatthew G. Knepley }
11846528b96dSMatthew G. Knepley 
118524cdb843SMatthew G. Knepley /*@
118624cdb843SMatthew G. Knepley   DMPlexSNESComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user
118724cdb843SMatthew G. Knepley 
118824cdb843SMatthew G. Knepley   Input Parameters:
118924cdb843SMatthew G. Knepley + dm - The mesh
119024cdb843SMatthew G. Knepley . X  - Local solution
119124cdb843SMatthew G. Knepley - user - The user context
119224cdb843SMatthew G. Knepley 
119324cdb843SMatthew G. Knepley   Output Parameter:
119424cdb843SMatthew G. Knepley . F  - Local output vector
119524cdb843SMatthew G. Knepley 
119624cdb843SMatthew G. Knepley   Level: developer
119724cdb843SMatthew G. Knepley 
11987a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction()
119924cdb843SMatthew G. Knepley @*/
120024cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user)
120124cdb843SMatthew G. Knepley {
12026da023fcSToby Isaac   DM             plex;
1203083401c6SMatthew G. Knepley   IS             allcellIS;
12046528b96dSMatthew G. Knepley   PetscInt       Nds, s;
120524cdb843SMatthew G. Knepley   PetscErrorCode ierr;
120624cdb843SMatthew G. Knepley 
120724cdb843SMatthew G. Knepley   PetscFunctionBegin;
12086da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
12096528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
12106528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
12116528b96dSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
12126528b96dSMatthew G. Knepley     PetscDS          ds;
12136528b96dSMatthew G. Knepley     IS               cellIS;
12146528b96dSMatthew G. Knepley     PetscHashFormKey key;
12156528b96dSMatthew G. Knepley 
12166528b96dSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr);
12176528b96dSMatthew G. Knepley     key.value = 0;
12186528b96dSMatthew G. Knepley     key.field = 0;
12196528b96dSMatthew G. Knepley     if (!key.label) {
12206528b96dSMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
12216528b96dSMatthew G. Knepley       cellIS = allcellIS;
12226528b96dSMatthew G. Knepley     } else {
12236528b96dSMatthew G. Knepley       IS pointIS;
12246528b96dSMatthew G. Knepley 
12256528b96dSMatthew G. Knepley       key.value = 1;
12266528b96dSMatthew G. Knepley       ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr);
12276528b96dSMatthew G. Knepley       ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
12286528b96dSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
12296528b96dSMatthew G. Knepley     }
12306528b96dSMatthew G. Knepley     ierr = DMPlexComputeResidual_Internal(plex, key, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);
12316528b96dSMatthew G. Knepley     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
12326528b96dSMatthew G. Knepley   }
12336528b96dSMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
12346528b96dSMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
12356528b96dSMatthew G. Knepley   PetscFunctionReturn(0);
12366528b96dSMatthew G. Knepley }
12376528b96dSMatthew G. Knepley 
12386528b96dSMatthew G. Knepley PetscErrorCode DMSNESComputeResidual(DM dm, Vec X, Vec F, void *user)
12396528b96dSMatthew G. Knepley {
12406528b96dSMatthew G. Knepley   DM             plex;
12416528b96dSMatthew G. Knepley   IS             allcellIS;
12426528b96dSMatthew G. Knepley   PetscInt       Nds, s;
12436528b96dSMatthew G. Knepley   PetscErrorCode ierr;
12446528b96dSMatthew G. Knepley 
12456528b96dSMatthew G. Knepley   PetscFunctionBegin;
12466528b96dSMatthew G. Knepley   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
12476528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
12486528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1249083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
1250083401c6SMatthew G. Knepley     PetscDS ds;
1251083401c6SMatthew G. Knepley     DMLabel label;
1252083401c6SMatthew G. Knepley     IS      cellIS;
1253083401c6SMatthew G. Knepley 
1254083401c6SMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr);
12556528b96dSMatthew G. Knepley     {
12566528b96dSMatthew G. Knepley       PetscHMapForm     resmap[2] = {ds->wf->f0, ds->wf->f1};
12576528b96dSMatthew G. Knepley       PetscWeakForm     wf;
12586528b96dSMatthew G. Knepley       PetscInt          Nm = 2, m, Nk = 0, k, kp, off = 0;
12596528b96dSMatthew G. Knepley       PetscHashFormKey *reskeys;
12606528b96dSMatthew G. Knepley 
12616528b96dSMatthew G. Knepley       /* Get unique residual keys */
12626528b96dSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
12636528b96dSMatthew G. Knepley         PetscInt Nkm;
12646528b96dSMatthew G. Knepley         ierr = PetscHMapFormGetSize(resmap[m], &Nkm);CHKERRQ(ierr);
12656528b96dSMatthew G. Knepley         Nk  += Nkm;
12666528b96dSMatthew G. Knepley       }
12676528b96dSMatthew G. Knepley       ierr = PetscMalloc1(Nk, &reskeys);CHKERRQ(ierr);
12686528b96dSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
12696528b96dSMatthew G. Knepley         ierr = PetscHMapFormGetKeys(resmap[m], &off, reskeys);CHKERRQ(ierr);
12706528b96dSMatthew G. Knepley       }
12716528b96dSMatthew G. Knepley       if (off != Nk) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk);
12726528b96dSMatthew G. Knepley       ierr = PetscHashFormKeySort(Nk, reskeys);CHKERRQ(ierr);
12736528b96dSMatthew G. Knepley       for (k = 0, kp = 1; kp < Nk; ++kp) {
12746528b96dSMatthew G. Knepley         if ((reskeys[k].label != reskeys[kp].label) || (reskeys[k].value != reskeys[kp].value)) {
12756528b96dSMatthew G. Knepley           ++k;
12766528b96dSMatthew G. Knepley           if (kp != k) reskeys[k] = reskeys[kp];
12776528b96dSMatthew G. Knepley         }
12786528b96dSMatthew G. Knepley       }
12796528b96dSMatthew G. Knepley       Nk = k;
12806528b96dSMatthew G. Knepley 
12816528b96dSMatthew G. Knepley       ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
12826528b96dSMatthew G. Knepley       for (k = 0; k < Nk; ++k) {
12836528b96dSMatthew G. Knepley         DMLabel  label = reskeys[k].label;
12846528b96dSMatthew G. Knepley         PetscInt val   = reskeys[k].value;
12856528b96dSMatthew G. Knepley 
1286083401c6SMatthew G. Knepley         if (!label) {
1287083401c6SMatthew G. Knepley           ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
1288083401c6SMatthew G. Knepley           cellIS = allcellIS;
1289083401c6SMatthew G. Knepley         } else {
1290083401c6SMatthew G. Knepley           IS pointIS;
1291083401c6SMatthew G. Knepley 
12926528b96dSMatthew G. Knepley           ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr);
1293083401c6SMatthew G. Knepley           ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
1294083401c6SMatthew G. Knepley           ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
12954a3e9fdbSToby Isaac         }
12966528b96dSMatthew G. Knepley         ierr = DMPlexComputeResidual_Internal(plex, reskeys[k], cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);
12974a3e9fdbSToby Isaac         ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
1298083401c6SMatthew G. Knepley       }
12996528b96dSMatthew G. Knepley       ierr = PetscFree(reskeys);CHKERRQ(ierr);
13006528b96dSMatthew G. Knepley     }
13016528b96dSMatthew G. Knepley   }
1302083401c6SMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
13039a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
130424cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
130524cdb843SMatthew G. Knepley }
130624cdb843SMatthew G. Knepley 
1307bdd6f66aSToby Isaac /*@
1308bdd6f66aSToby Isaac   DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X
1309bdd6f66aSToby Isaac 
1310bdd6f66aSToby Isaac   Input Parameters:
1311bdd6f66aSToby Isaac + dm - The mesh
1312bdd6f66aSToby Isaac - user - The user context
1313bdd6f66aSToby Isaac 
1314bdd6f66aSToby Isaac   Output Parameter:
1315bdd6f66aSToby Isaac . X  - Local solution
1316bdd6f66aSToby Isaac 
1317bdd6f66aSToby Isaac   Level: developer
1318bdd6f66aSToby Isaac 
13197a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction()
1320bdd6f66aSToby Isaac @*/
1321bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user)
1322bdd6f66aSToby Isaac {
1323bdd6f66aSToby Isaac   DM             plex;
1324bdd6f66aSToby Isaac   PetscErrorCode ierr;
1325bdd6f66aSToby Isaac 
1326bdd6f66aSToby Isaac   PetscFunctionBegin;
1327bdd6f66aSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
1328bdd6f66aSToby Isaac   ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr);
1329bdd6f66aSToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
1330bdd6f66aSToby Isaac   PetscFunctionReturn(0);
1331bdd6f66aSToby Isaac }
1332bdd6f66aSToby Isaac 
13337a73cf09SMatthew G. Knepley /*@
13347a73cf09SMatthew G. Knepley   DMPlexComputeJacobianAction - Form the local portion of the Jacobian action Z = J(X) Y at the local solution X using pointwise functions specified by the user.
13357a73cf09SMatthew G. Knepley 
13367a73cf09SMatthew G. Knepley   Input Parameters:
13377a73cf09SMatthew G. Knepley + dm - The mesh
13387a73cf09SMatthew G. Knepley . cellIS -
13397a73cf09SMatthew G. Knepley . t  - The time
13407a73cf09SMatthew G. Knepley . X_tShift - The multiplier for the Jacobian with repsect to X_t
13417a73cf09SMatthew G. Knepley . X  - Local solution vector
13427a73cf09SMatthew G. Knepley . X_t  - Time-derivative of the local solution vector
13437a73cf09SMatthew G. Knepley . Y  - Local input vector
13447a73cf09SMatthew G. Knepley - user - The user context
13457a73cf09SMatthew G. Knepley 
13467a73cf09SMatthew G. Knepley   Output Parameter:
13477a73cf09SMatthew G. Knepley . Z - Local output vector
13487a73cf09SMatthew G. Knepley 
13497a73cf09SMatthew G. Knepley   Note:
13507a73cf09SMatthew G. Knepley   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
13517a73cf09SMatthew G. Knepley   like a GPU, or vectorize on a multicore machine.
13527a73cf09SMatthew G. Knepley 
13537a73cf09SMatthew G. Knepley   Level: developer
13547a73cf09SMatthew G. Knepley 
13557a73cf09SMatthew G. Knepley .seealso: FormFunctionLocal()
13567a73cf09SMatthew G. Knepley @*/
13577a73cf09SMatthew G. Knepley PetscErrorCode DMPlexComputeJacobianAction(DM dm, IS cellIS, PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Vec Y, Vec Z, void *user)
1358a925c78cSMatthew G. Knepley {
1359a925c78cSMatthew G. Knepley   DM_Plex          *mesh  = (DM_Plex *) dm->data;
1360a925c78cSMatthew G. Knepley   const char       *name  = "Jacobian";
1361*9a2a23afSMatthew G. Knepley   DM                dmAux = NULL, plex, plexAux = NULL;
1362a6e0b375SMatthew G. Knepley   DMEnclosureType   encAux;
1363c330f8ffSToby Isaac   Vec               A;
1364a925c78cSMatthew G. Knepley   PetscDS           prob, probAux = NULL;
1365a925c78cSMatthew G. Knepley   PetscQuadrature   quad;
1366a925c78cSMatthew G. Knepley   PetscSection      section, globalSection, sectionAux;
1367a925c78cSMatthew G. Knepley   PetscScalar      *elemMat, *elemMatD, *u, *u_t, *a = NULL, *y, *z;
13689044fa66SMatthew G. Knepley   PetscInt          Nf, fieldI, fieldJ;
13694d0b9603SSander Arens   PetscInt          totDim, totDimAux = 0;
13709044fa66SMatthew G. Knepley   const PetscInt   *cells;
13719044fa66SMatthew G. Knepley   PetscInt          cStart, cEnd, numCells, c;
137275b37a90SMatthew G. Knepley   PetscBool         hasDyn;
1373c330f8ffSToby Isaac   DMField           coordField;
13746528b96dSMatthew G. Knepley   PetscHashFormKey  key;
1375a925c78cSMatthew G. Knepley   PetscErrorCode    ierr;
1376a925c78cSMatthew G. Knepley 
1377a925c78cSMatthew G. Knepley   PetscFunctionBegin;
1378a925c78cSMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
13797a73cf09SMatthew G. Knepley   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
13807a73cf09SMatthew G. Knepley   if (!cellIS) {
13817a73cf09SMatthew G. Knepley     PetscInt depth;
13827a73cf09SMatthew G. Knepley 
13837a73cf09SMatthew G. Knepley     ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
13847a73cf09SMatthew G. Knepley     ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr);
13857a73cf09SMatthew G. Knepley     if (!cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr);}
13867a73cf09SMatthew G. Knepley   } else {
13877a73cf09SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) cellIS);CHKERRQ(ierr);
13887a73cf09SMatthew G. Knepley   }
13896528b96dSMatthew G. Knepley   key.label = NULL;
13906528b96dSMatthew G. Knepley   key.value = 0;
139192fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
1392e87a4003SBarry Smith   ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);
1393d28747ceSMatthew G. Knepley   ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr);
1394d28747ceSMatthew G. Knepley   ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr);
1395d28747ceSMatthew G. Knepley   ierr = DMGetCellDS(dm, cells ? cells[cStart] : cStart, &prob);CHKERRQ(ierr);
1396d28747ceSMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
1397a925c78cSMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
1398a925c78cSMatthew G. Knepley   ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr);
1399a925c78cSMatthew G. Knepley   hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
1400*9a2a23afSMatthew G. Knepley   ierr = DMGetAuxiliaryVec(dm, NULL, 0, &A);CHKERRQ(ierr);
1401*9a2a23afSMatthew G. Knepley   if (A) {
1402*9a2a23afSMatthew G. Knepley     ierr = VecGetDM(A, &dmAux);CHKERRQ(ierr);
1403a6e0b375SMatthew G. Knepley     ierr = DMGetEnclosureRelation(dmAux, dm, &encAux);CHKERRQ(ierr);
14047a73cf09SMatthew G. Knepley     ierr = DMConvert(dmAux, DMPLEX, &plexAux);CHKERRQ(ierr);
140592fd8e1eSJed Brown     ierr = DMGetLocalSection(plexAux, &sectionAux);CHKERRQ(ierr);
1406a925c78cSMatthew G. Knepley     ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr);
1407a925c78cSMatthew G. Knepley     ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);
1408a925c78cSMatthew G. Knepley   }
1409a925c78cSMatthew G. Knepley   ierr = VecSet(Z, 0.0);CHKERRQ(ierr);
1410a925c78cSMatthew G. Knepley   ierr = PetscMalloc6(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*totDim*totDim,&elemMat,hasDyn ? numCells*totDim*totDim : 0, &elemMatD,numCells*totDim,&y,totDim,&z);CHKERRQ(ierr);
1411a925c78cSMatthew G. Knepley   if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);}
14124a3e9fdbSToby Isaac   ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr);
1413a925c78cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
14149044fa66SMatthew G. Knepley     const PetscInt cell = cells ? cells[c] : c;
14159044fa66SMatthew G. Knepley     const PetscInt cind = c - cStart;
1416a925c78cSMatthew G. Knepley     PetscScalar   *x = NULL,  *x_t = NULL;
1417a925c78cSMatthew G. Knepley     PetscInt       i;
1418a925c78cSMatthew G. Knepley 
14199044fa66SMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
14209044fa66SMatthew G. Knepley     for (i = 0; i < totDim; ++i) u[cind*totDim+i] = x[i];
14219044fa66SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr);
1422a925c78cSMatthew G. Knepley     if (X_t) {
14239044fa66SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
14249044fa66SMatthew G. Knepley       for (i = 0; i < totDim; ++i) u_t[cind*totDim+i] = x_t[i];
14259044fa66SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr);
1426a925c78cSMatthew G. Knepley     }
1427a925c78cSMatthew G. Knepley     if (dmAux) {
142844171101SMatthew G. Knepley       PetscInt subcell;
1429a6e0b375SMatthew G. Knepley       ierr = DMGetEnclosurePoint(dmAux, dm, encAux, cell, &subcell);CHKERRQ(ierr);
143044171101SMatthew G. Knepley       ierr = DMPlexVecGetClosure(plexAux, sectionAux, A, subcell, NULL, &x);CHKERRQ(ierr);
14319044fa66SMatthew G. Knepley       for (i = 0; i < totDimAux; ++i) a[cind*totDimAux+i] = x[i];
143244171101SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(plexAux, sectionAux, A, subcell, NULL, &x);CHKERRQ(ierr);
1433a925c78cSMatthew G. Knepley     }
14349044fa66SMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr);
14359044fa66SMatthew G. Knepley     for (i = 0; i < totDim; ++i) y[cind*totDim+i] = x[i];
14369044fa66SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr);
1437a925c78cSMatthew G. Knepley   }
1438580bdb30SBarry Smith   ierr = PetscArrayzero(elemMat, numCells*totDim*totDim);CHKERRQ(ierr);
1439580bdb30SBarry Smith   if (hasDyn)  {ierr = PetscArrayzero(elemMatD, numCells*totDim*totDim);CHKERRQ(ierr);}
1440a925c78cSMatthew G. Knepley   for (fieldI = 0; fieldI < Nf; ++fieldI) {
1441a925c78cSMatthew G. Knepley     PetscFE  fe;
1442c330f8ffSToby Isaac     PetscInt Nb;
1443a925c78cSMatthew G. Knepley     /* Conforming batches */
1444a925c78cSMatthew G. Knepley     PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
1445a925c78cSMatthew G. Knepley     /* Remainder */
1446c330f8ffSToby Isaac     PetscInt Nr, offset, Nq;
1447c330f8ffSToby Isaac     PetscQuadrature qGeom = NULL;
1448b7260050SToby Isaac     PetscInt    maxDegree;
1449c330f8ffSToby Isaac     PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL;
1450a925c78cSMatthew G. Knepley 
1451a925c78cSMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
1452a925c78cSMatthew G. Knepley     ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
1453a925c78cSMatthew G. Knepley     ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
1454a925c78cSMatthew G. Knepley     ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr);
1455b7260050SToby Isaac     ierr = DMFieldGetDegree(coordField,cellIS,NULL,&maxDegree);CHKERRQ(ierr);
1456b7260050SToby Isaac     if (maxDegree <= 1) {ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr);}
1457c330f8ffSToby Isaac     if (!qGeom) {
1458c330f8ffSToby Isaac       ierr = PetscFEGetQuadrature(fe,&qGeom);CHKERRQ(ierr);
1459c330f8ffSToby Isaac       ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr);
1460c330f8ffSToby Isaac     }
1461c330f8ffSToby Isaac     ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
14624a3e9fdbSToby Isaac     ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
1463c330f8ffSToby Isaac     blockSize = Nb;
1464a925c78cSMatthew G. Knepley     batchSize = numBlocks * blockSize;
1465a925c78cSMatthew G. Knepley     ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr);
1466a925c78cSMatthew G. Knepley     numChunks = numCells / (numBatches*batchSize);
1467a925c78cSMatthew G. Knepley     Ne        = numChunks*numBatches*batchSize;
1468a925c78cSMatthew G. Knepley     Nr        = numCells % (numBatches*batchSize);
1469a925c78cSMatthew G. Knepley     offset    = numCells - Nr;
1470c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr);
1471c330f8ffSToby Isaac     ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr);
1472a925c78cSMatthew G. Knepley     for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
14736528b96dSMatthew G. Knepley       key.field = fieldI*Nf + fieldJ;
14746528b96dSMatthew G. Knepley       ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr);
14756528b96dSMatthew G. Knepley       ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN, key, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMat[offset*totDim*totDim]);CHKERRQ(ierr);
1476a925c78cSMatthew G. Knepley       if (hasDyn) {
14776528b96dSMatthew G. Knepley         ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN_DYN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr);
14786528b96dSMatthew G. Knepley         ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN_DYN, key, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMatD[offset*totDim*totDim]);CHKERRQ(ierr);
1479a925c78cSMatthew G. Knepley       }
1480a925c78cSMatthew G. Knepley     }
1481c330f8ffSToby Isaac     ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr);
1482c330f8ffSToby Isaac     ierr = PetscFEGeomRestoreChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr);
14834a3e9fdbSToby Isaac     ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr);
1484c330f8ffSToby Isaac     ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr);
1485a925c78cSMatthew G. Knepley   }
1486a925c78cSMatthew G. Knepley   if (hasDyn) {
14879044fa66SMatthew G. Knepley     for (c = 0; c < numCells*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c];
1488a925c78cSMatthew G. Knepley   }
1489a925c78cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
14909044fa66SMatthew G. Knepley     const PetscInt     cell = cells ? cells[c] : c;
14919044fa66SMatthew G. Knepley     const PetscInt     cind = c - cStart;
1492a925c78cSMatthew G. Knepley     const PetscBLASInt M = totDim, one = 1;
1493a925c78cSMatthew G. Knepley     const PetscScalar  a = 1.0, b = 0.0;
1494a925c78cSMatthew G. Knepley 
14959044fa66SMatthew G. Knepley     PetscStackCallBLAS("BLASgemv", BLASgemv_("N", &M, &M, &a, &elemMat[cind*totDim*totDim], &M, &y[cind*totDim], &one, &b, z, &one));
1496a925c78cSMatthew G. Knepley     if (mesh->printFEM > 1) {
14979044fa66SMatthew G. Knepley       ierr = DMPrintCellMatrix(c, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr);
14989044fa66SMatthew G. Knepley       ierr = DMPrintCellVector(c, "Y",  totDim, &y[cind*totDim]);CHKERRQ(ierr);
1499a925c78cSMatthew G. Knepley       ierr = DMPrintCellVector(c, "Z",  totDim, z);CHKERRQ(ierr);
1500a925c78cSMatthew G. Knepley     }
15019044fa66SMatthew G. Knepley     ierr = DMPlexVecSetClosure(dm, section, Z, cell, z, ADD_VALUES);CHKERRQ(ierr);
1502a925c78cSMatthew G. Knepley   }
1503a925c78cSMatthew G. Knepley   ierr = PetscFree6(u,u_t,elemMat,elemMatD,y,z);CHKERRQ(ierr);
1504a925c78cSMatthew G. Knepley   if (mesh->printFEM) {
1505ea13f565SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)Z), "Z:\n");CHKERRQ(ierr);
1506a8c5bd36SStefano Zampini     ierr = VecView(Z, NULL);CHKERRQ(ierr);
1507a925c78cSMatthew G. Knepley   }
15087a73cf09SMatthew G. Knepley   ierr = PetscFree(a);CHKERRQ(ierr);
15097a73cf09SMatthew G. Knepley   ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
15107a73cf09SMatthew G. Knepley   ierr = DMDestroy(&plexAux);CHKERRQ(ierr);
15117a73cf09SMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
1512a925c78cSMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr);
1513a925c78cSMatthew G. Knepley   PetscFunctionReturn(0);
1514a925c78cSMatthew G. Knepley }
1515a925c78cSMatthew G. Knepley 
151624cdb843SMatthew G. Knepley /*@
151724cdb843SMatthew G. Knepley   DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user.
151824cdb843SMatthew G. Knepley 
151924cdb843SMatthew G. Knepley   Input Parameters:
152024cdb843SMatthew G. Knepley + dm - The mesh
152124cdb843SMatthew G. Knepley . X  - Local input vector
152224cdb843SMatthew G. Knepley - user - The user context
152324cdb843SMatthew G. Knepley 
152424cdb843SMatthew G. Knepley   Output Parameter:
152524cdb843SMatthew G. Knepley . Jac  - Jacobian matrix
152624cdb843SMatthew G. Knepley 
152724cdb843SMatthew G. Knepley   Note:
152824cdb843SMatthew G. Knepley   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
152924cdb843SMatthew G. Knepley   like a GPU, or vectorize on a multicore machine.
153024cdb843SMatthew G. Knepley 
153124cdb843SMatthew G. Knepley   Level: developer
153224cdb843SMatthew G. Knepley 
153324cdb843SMatthew G. Knepley .seealso: FormFunctionLocal()
153424cdb843SMatthew G. Knepley @*/
153524cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user)
153624cdb843SMatthew G. Knepley {
15376da023fcSToby Isaac   DM             plex;
1538083401c6SMatthew G. Knepley   IS             allcellIS;
1539f04eb4edSMatthew G. Knepley   PetscBool      hasJac, hasPrec;
15406528b96dSMatthew G. Knepley   PetscInt       Nds, s;
154124cdb843SMatthew G. Knepley   PetscErrorCode ierr;
154224cdb843SMatthew G. Knepley 
154324cdb843SMatthew G. Knepley   PetscFunctionBegin;
15446da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
15456528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
15466528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1547083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
1548083401c6SMatthew G. Knepley     PetscDS          ds;
1549083401c6SMatthew G. Knepley     IS               cellIS;
15506528b96dSMatthew G. Knepley     PetscHashFormKey key;
1551083401c6SMatthew G. Knepley 
15526528b96dSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr);
15536528b96dSMatthew G. Knepley     key.value = 0;
15546528b96dSMatthew G. Knepley     key.field = 0;
15556528b96dSMatthew G. Knepley     if (!key.label) {
1556083401c6SMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
1557083401c6SMatthew G. Knepley       cellIS = allcellIS;
1558083401c6SMatthew G. Knepley     } else {
1559083401c6SMatthew G. Knepley       IS pointIS;
1560083401c6SMatthew G. Knepley 
15616528b96dSMatthew G. Knepley       key.value = 1;
15626528b96dSMatthew G. Knepley       ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr);
1563083401c6SMatthew G. Knepley       ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
1564083401c6SMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1565083401c6SMatthew G. Knepley     }
1566083401c6SMatthew G. Knepley     if (!s) {
1567083401c6SMatthew G. Knepley       ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr);
1568083401c6SMatthew G. Knepley       ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr);
1569f04eb4edSMatthew G. Knepley       if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);}
1570f04eb4edSMatthew G. Knepley       ierr = MatZeroEntries(JacP);CHKERRQ(ierr);
1571083401c6SMatthew G. Knepley     }
15726528b96dSMatthew G. Knepley     ierr = DMPlexComputeJacobian_Internal(plex, key, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr);
15734a3e9fdbSToby Isaac     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
1574083401c6SMatthew G. Knepley   }
1575083401c6SMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
15769a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
157724cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
157824cdb843SMatthew G. Knepley }
15791878804aSMatthew G. Knepley 
158038cfc46eSPierre Jolivet /*
158138cfc46eSPierre Jolivet      MatComputeNeumannOverlap - Computes an unassembled (Neumann) local overlapping Mat in nonlinear context.
158238cfc46eSPierre Jolivet 
158338cfc46eSPierre Jolivet    Input Parameters:
158438cfc46eSPierre Jolivet +     X - SNES linearization point
158538cfc46eSPierre Jolivet .     ovl - index set of overlapping subdomains
158638cfc46eSPierre Jolivet 
158738cfc46eSPierre Jolivet    Output Parameter:
158838cfc46eSPierre Jolivet .     J - unassembled (Neumann) local matrix
158938cfc46eSPierre Jolivet 
159038cfc46eSPierre Jolivet    Level: intermediate
159138cfc46eSPierre Jolivet 
159238cfc46eSPierre Jolivet .seealso: DMCreateNeumannOverlap(), MATIS, PCHPDDMSetAuxiliaryMat()
159338cfc46eSPierre Jolivet */
159438cfc46eSPierre Jolivet static PetscErrorCode MatComputeNeumannOverlap_Plex(Mat J, PetscReal t, Vec X, Vec X_t, PetscReal s, IS ovl, void *ctx)
159538cfc46eSPierre Jolivet {
159638cfc46eSPierre Jolivet   SNES           snes;
159738cfc46eSPierre Jolivet   Mat            pJ;
159838cfc46eSPierre Jolivet   DM             ovldm,origdm;
159938cfc46eSPierre Jolivet   DMSNES         sdm;
160038cfc46eSPierre Jolivet   PetscErrorCode (*bfun)(DM,Vec,void*);
160138cfc46eSPierre Jolivet   PetscErrorCode (*jfun)(DM,Vec,Mat,Mat,void*);
160238cfc46eSPierre Jolivet   void           *bctx,*jctx;
160338cfc46eSPierre Jolivet   PetscErrorCode ierr;
160438cfc46eSPierre Jolivet 
160538cfc46eSPierre Jolivet   PetscFunctionBegin;
160638cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_MATIS",(PetscObject*)&pJ);CHKERRQ(ierr);
160738cfc46eSPierre Jolivet   if (!pJ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing overlapping Mat");CHKERRQ(ierr);
160838cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Original_HPDDM",(PetscObject*)&origdm);CHKERRQ(ierr);
160938cfc46eSPierre Jolivet   if (!origdm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing original DM");CHKERRQ(ierr);
161038cfc46eSPierre Jolivet   ierr = MatGetDM(pJ,&ovldm);CHKERRQ(ierr);
161138cfc46eSPierre Jolivet   ierr = DMSNESGetBoundaryLocal(origdm,&bfun,&bctx);CHKERRQ(ierr);
161238cfc46eSPierre Jolivet   ierr = DMSNESSetBoundaryLocal(ovldm,bfun,bctx);CHKERRQ(ierr);
161338cfc46eSPierre Jolivet   ierr = DMSNESGetJacobianLocal(origdm,&jfun,&jctx);CHKERRQ(ierr);
161438cfc46eSPierre Jolivet   ierr = DMSNESSetJacobianLocal(ovldm,jfun,jctx);CHKERRQ(ierr);
161538cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject*)&snes);CHKERRQ(ierr);
161638cfc46eSPierre Jolivet   if (!snes) {
161738cfc46eSPierre Jolivet     ierr = SNESCreate(PetscObjectComm((PetscObject)ovl),&snes);CHKERRQ(ierr);
161838cfc46eSPierre Jolivet     ierr = SNESSetDM(snes,ovldm);CHKERRQ(ierr);
161938cfc46eSPierre Jolivet     ierr = PetscObjectCompose((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject)snes);CHKERRQ(ierr);
162038cfc46eSPierre Jolivet     ierr = PetscObjectDereference((PetscObject)snes);CHKERRQ(ierr);
162138cfc46eSPierre Jolivet   }
162238cfc46eSPierre Jolivet   ierr = DMGetDMSNES(ovldm,&sdm);CHKERRQ(ierr);
162338cfc46eSPierre Jolivet   ierr = VecLockReadPush(X);CHKERRQ(ierr);
162438cfc46eSPierre Jolivet   PetscStackPush("SNES user Jacobian function");
162538cfc46eSPierre Jolivet   ierr = (*sdm->ops->computejacobian)(snes,X,pJ,pJ,sdm->jacobianctx);CHKERRQ(ierr);
162638cfc46eSPierre Jolivet   PetscStackPop;
162738cfc46eSPierre Jolivet   ierr = VecLockReadPop(X);CHKERRQ(ierr);
162838cfc46eSPierre Jolivet   /* this is a no-hop, just in case we decide to change the placeholder for the local Neumann matrix */
162938cfc46eSPierre Jolivet   {
163038cfc46eSPierre Jolivet     Mat locpJ;
163138cfc46eSPierre Jolivet 
163238cfc46eSPierre Jolivet     ierr = MatISGetLocalMat(pJ,&locpJ);CHKERRQ(ierr);
163338cfc46eSPierre Jolivet     ierr = MatCopy(locpJ,J,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
163438cfc46eSPierre Jolivet   }
163538cfc46eSPierre Jolivet   PetscFunctionReturn(0);
163638cfc46eSPierre Jolivet }
163738cfc46eSPierre Jolivet 
1638a925c78cSMatthew G. Knepley /*@
16399f520fc2SToby Isaac   DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian.
16409f520fc2SToby Isaac 
16419f520fc2SToby Isaac   Input Parameters:
16429f520fc2SToby Isaac + dm - The DM object
1643dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary())
16449f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual())
16459f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian())
16461a244344SSatish Balay 
16471a244344SSatish Balay   Level: developer
16489f520fc2SToby Isaac @*/
16499f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx)
16509f520fc2SToby Isaac {
16519f520fc2SToby Isaac   PetscErrorCode ierr;
16529f520fc2SToby Isaac 
16539f520fc2SToby Isaac   PetscFunctionBegin;
16549f520fc2SToby Isaac   ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr);
16559f520fc2SToby Isaac   ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr);
16569f520fc2SToby Isaac   ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr);
165738cfc46eSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",MatComputeNeumannOverlap_Plex);CHKERRQ(ierr);
16589f520fc2SToby Isaac   PetscFunctionReturn(0);
16599f520fc2SToby Isaac }
16609f520fc2SToby Isaac 
1661f017bcb6SMatthew G. Knepley /*@C
1662f017bcb6SMatthew G. Knepley   DMSNESCheckDiscretization - Check the discretization error of the exact solution
1663f017bcb6SMatthew G. Knepley 
1664f017bcb6SMatthew G. Knepley   Input Parameters:
1665f017bcb6SMatthew G. Knepley + snes - the SNES object
1666f017bcb6SMatthew G. Knepley . dm   - the DM
1667f2cacb80SMatthew G. Knepley . t    - the time
1668f017bcb6SMatthew G. Knepley . u    - a DM vector
1669f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1670f017bcb6SMatthew G. Knepley 
1671f3c94560SMatthew G. Knepley   Output Parameters:
1672f3c94560SMatthew G. Knepley . error - An array which holds the discretization error in each field, or NULL
1673f3c94560SMatthew G. Knepley 
16747f96f943SMatthew G. Knepley   Note: The user must call PetscDSSetExactSolution() beforehand
16757f96f943SMatthew G. Knepley 
1676f017bcb6SMatthew G. Knepley   Level: developer
1677f017bcb6SMatthew G. Knepley 
16787f96f943SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckResidual(), DMSNESCheckJacobian(), PetscDSSetExactSolution()
1679f017bcb6SMatthew G. Knepley @*/
1680f2cacb80SMatthew G. Knepley PetscErrorCode DMSNESCheckDiscretization(SNES snes, DM dm, PetscReal t, Vec u, PetscReal tol, PetscReal error[])
16811878804aSMatthew G. Knepley {
1682f017bcb6SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
1683f017bcb6SMatthew G. Knepley   void            **ectxs;
1684f3c94560SMatthew G. Knepley   PetscReal        *err;
16857f96f943SMatthew G. Knepley   MPI_Comm          comm;
16867f96f943SMatthew G. Knepley   PetscInt          Nf, f;
16871878804aSMatthew G. Knepley   PetscErrorCode    ierr;
16881878804aSMatthew G. Knepley 
16891878804aSMatthew G. Knepley   PetscFunctionBegin;
1690f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1691f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1692f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
1693534a8f05SLisandro Dalcin   if (error) PetscValidRealPointer(error, 6);
16947f96f943SMatthew G. Knepley 
1695f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, t, u, NULL);CHKERRQ(ierr);
16967f96f943SMatthew G. Knepley   ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr);
16977f96f943SMatthew G. Knepley 
1698f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1699f017bcb6SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
1700083401c6SMatthew G. Knepley   ierr = PetscCalloc3(Nf, &exacts, Nf, &ectxs, PetscMax(1, Nf), &err);CHKERRQ(ierr);
17017f96f943SMatthew G. Knepley   {
17027f96f943SMatthew G. Knepley     PetscInt Nds, s;
17037f96f943SMatthew G. Knepley 
1704083401c6SMatthew G. Knepley     ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1705083401c6SMatthew G. Knepley     for (s = 0; s < Nds; ++s) {
17067f96f943SMatthew G. Knepley       PetscDS         ds;
1707083401c6SMatthew G. Knepley       DMLabel         label;
1708083401c6SMatthew G. Knepley       IS              fieldIS;
17097f96f943SMatthew G. Knepley       const PetscInt *fields;
17107f96f943SMatthew G. Knepley       PetscInt        dsNf, f;
1711083401c6SMatthew G. Knepley 
1712083401c6SMatthew G. Knepley       ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr);
1713083401c6SMatthew G. Knepley       ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr);
1714083401c6SMatthew G. Knepley       ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);
1715083401c6SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) {
1716083401c6SMatthew G. Knepley         const PetscInt field = fields[f];
1717083401c6SMatthew G. Knepley         ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr);
1718083401c6SMatthew G. Knepley       }
1719083401c6SMatthew G. Knepley       ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);
1720083401c6SMatthew G. Knepley     }
1721083401c6SMatthew G. Knepley   }
1722f017bcb6SMatthew G. Knepley   if (Nf > 1) {
1723f2cacb80SMatthew G. Knepley     ierr = DMComputeL2FieldDiff(dm, t, exacts, ectxs, u, err);CHKERRQ(ierr);
1724f017bcb6SMatthew G. Knepley     if (tol >= 0.0) {
1725f017bcb6SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
1726f3c94560SMatthew G. Knepley         if (err[f] > tol) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g for field %D exceeds tolerance %g", (double) err[f], f, (double) tol);
17271878804aSMatthew G. Knepley       }
1728b878532fSMatthew G. Knepley     } else if (error) {
1729b878532fSMatthew G. Knepley       for (f = 0; f < Nf; ++f) error[f] = err[f];
17301878804aSMatthew G. Knepley     } else {
1731f017bcb6SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr);
1732f017bcb6SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
1733f017bcb6SMatthew G. Knepley         if (f) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);}
1734f3c94560SMatthew G. Knepley         ierr = PetscPrintf(comm, "%g", (double)err[f]);CHKERRQ(ierr);
17351878804aSMatthew G. Knepley       }
1736f017bcb6SMatthew G. Knepley       ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr);
1737f017bcb6SMatthew G. Knepley     }
1738f017bcb6SMatthew G. Knepley   } else {
1739f2cacb80SMatthew G. Knepley     ierr = DMComputeL2Diff(dm, t, exacts, ectxs, u, &err[0]);CHKERRQ(ierr);
1740f017bcb6SMatthew G. Knepley     if (tol >= 0.0) {
1741f3c94560SMatthew G. Knepley       if (err[0] > tol) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g exceeds tolerance %g", (double) err[0], (double) tol);
1742b878532fSMatthew G. Knepley     } else if (error) {
1743b878532fSMatthew G. Knepley       error[0] = err[0];
1744f017bcb6SMatthew G. Knepley     } else {
1745f3c94560SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: %g\n", (double) err[0]);CHKERRQ(ierr);
1746f017bcb6SMatthew G. Knepley     }
1747f017bcb6SMatthew G. Knepley   }
1748f3c94560SMatthew G. Knepley   ierr = PetscFree3(exacts, ectxs, err);CHKERRQ(ierr);
1749f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1750f017bcb6SMatthew G. Knepley }
1751f017bcb6SMatthew G. Knepley 
1752f017bcb6SMatthew G. Knepley /*@C
1753f017bcb6SMatthew G. Knepley   DMSNESCheckResidual - Check the residual of the exact solution
1754f017bcb6SMatthew G. Knepley 
1755f017bcb6SMatthew G. Knepley   Input Parameters:
1756f017bcb6SMatthew G. Knepley + snes - the SNES object
1757f017bcb6SMatthew G. Knepley . dm   - the DM
1758f017bcb6SMatthew G. Knepley . u    - a DM vector
1759f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1760f017bcb6SMatthew G. Knepley 
1761f3c94560SMatthew G. Knepley   Output Parameters:
1762f3c94560SMatthew G. Knepley . residual - The residual norm of the exact solution, or NULL
1763f3c94560SMatthew G. Knepley 
1764f017bcb6SMatthew G. Knepley   Level: developer
1765f017bcb6SMatthew G. Knepley 
1766f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckJacobian()
1767f017bcb6SMatthew G. Knepley @*/
1768f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckResidual(SNES snes, DM dm, Vec u, PetscReal tol, PetscReal *residual)
1769f017bcb6SMatthew G. Knepley {
1770f017bcb6SMatthew G. Knepley   MPI_Comm       comm;
1771f017bcb6SMatthew G. Knepley   Vec            r;
1772f017bcb6SMatthew G. Knepley   PetscReal      res;
1773f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1774f017bcb6SMatthew G. Knepley 
1775f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1776f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1777f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1778f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
1779534a8f05SLisandro Dalcin   if (residual) PetscValidRealPointer(residual, 5);
1780f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1781f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr);
1782f017bcb6SMatthew G. Knepley   ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
17831878804aSMatthew G. Knepley   ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr);
17841878804aSMatthew G. Knepley   ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr);
1785f017bcb6SMatthew G. Knepley   if (tol >= 0.0) {
1786f017bcb6SMatthew G. Knepley     if (res > tol) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "L_2 Residual %g exceeds tolerance %g", (double) res, (double) tol);
1787b878532fSMatthew G. Knepley   } else if (residual) {
1788b878532fSMatthew G. Knepley     *residual = res;
1789f017bcb6SMatthew G. Knepley   } else {
1790f017bcb6SMatthew G. Knepley     ierr = PetscPrintf(comm, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr);
17911878804aSMatthew G. Knepley     ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr);
17921878804aSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr);
1793685405a1SBarry Smith     ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr);
1794685405a1SBarry Smith     ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr);
1795f017bcb6SMatthew G. Knepley   }
1796f017bcb6SMatthew G. Knepley   ierr = VecDestroy(&r);CHKERRQ(ierr);
1797f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1798f017bcb6SMatthew G. Knepley }
1799f017bcb6SMatthew G. Knepley 
1800f017bcb6SMatthew G. Knepley /*@C
1801f3c94560SMatthew G. Knepley   DMSNESCheckJacobian - Check the Jacobian of the exact solution against the residual using the Taylor Test
1802f017bcb6SMatthew G. Knepley 
1803f017bcb6SMatthew G. Knepley   Input Parameters:
1804f017bcb6SMatthew G. Knepley + snes - the SNES object
1805f017bcb6SMatthew G. Knepley . dm   - the DM
1806f017bcb6SMatthew G. Knepley . u    - a DM vector
1807f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1808f017bcb6SMatthew G. Knepley 
1809f3c94560SMatthew G. Knepley   Output Parameters:
1810f3c94560SMatthew G. Knepley + isLinear - Flag indicaing that the function looks linear, or NULL
1811f3c94560SMatthew G. Knepley - convRate - The rate of convergence of the linear model, or NULL
1812f3c94560SMatthew G. Knepley 
1813f017bcb6SMatthew G. Knepley   Level: developer
1814f017bcb6SMatthew G. Knepley 
1815f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckResidual()
1816f017bcb6SMatthew G. Knepley @*/
1817f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckJacobian(SNES snes, DM dm, Vec u, PetscReal tol, PetscBool *isLinear, PetscReal *convRate)
1818f017bcb6SMatthew G. Knepley {
1819f017bcb6SMatthew G. Knepley   MPI_Comm       comm;
1820f017bcb6SMatthew G. Knepley   PetscDS        ds;
1821f017bcb6SMatthew G. Knepley   Mat            J, M;
1822f017bcb6SMatthew G. Knepley   MatNullSpace   nullspace;
1823f3c94560SMatthew G. Knepley   PetscReal      slope, intercept;
18247f96f943SMatthew G. Knepley   PetscBool      hasJac, hasPrec, isLin = PETSC_FALSE;
1825f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1826f017bcb6SMatthew G. Knepley 
1827f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1828f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1829f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1830f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
1831534a8f05SLisandro Dalcin   if (isLinear) PetscValidBoolPointer(isLinear, 5);
1832534a8f05SLisandro Dalcin   if (convRate) PetscValidRealPointer(convRate, 5);
1833f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1834f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr);
1835f017bcb6SMatthew G. Knepley   /* Create and view matrices */
1836f017bcb6SMatthew G. Knepley   ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr);
18377f96f943SMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1838f017bcb6SMatthew G. Knepley   ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr);
1839f017bcb6SMatthew G. Knepley   ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr);
1840282e7bb4SMatthew G. Knepley   if (hasJac && hasPrec) {
1841282e7bb4SMatthew G. Knepley     ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr);
1842282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr);
1843f017bcb6SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) M, "Preconditioning Matrix");CHKERRQ(ierr);
1844282e7bb4SMatthew G. Knepley     ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr);
1845282e7bb4SMatthew G. Knepley     ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr);
1846282e7bb4SMatthew G. Knepley     ierr = MatDestroy(&M);CHKERRQ(ierr);
1847282e7bb4SMatthew G. Knepley   } else {
1848282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr);
1849282e7bb4SMatthew G. Knepley   }
1850f017bcb6SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) J, "Jacobian");CHKERRQ(ierr);
1851282e7bb4SMatthew G. Knepley   ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr);
1852282e7bb4SMatthew G. Knepley   ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr);
1853f017bcb6SMatthew G. Knepley   /* Check nullspace */
1854f017bcb6SMatthew G. Knepley   ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
1855f017bcb6SMatthew G. Knepley   if (nullspace) {
18561878804aSMatthew G. Knepley     PetscBool isNull;
1857f017bcb6SMatthew G. Knepley     ierr = MatNullSpaceTest(nullspace, J, &isNull);CHKERRQ(ierr);
1858f017bcb6SMatthew G. Knepley     if (!isNull) SETERRQ(comm, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid.");
18591878804aSMatthew G. Knepley   }
1860f017bcb6SMatthew G. Knepley   /* Taylor test */
1861f017bcb6SMatthew G. Knepley   {
1862f017bcb6SMatthew G. Knepley     PetscRandom rand;
1863f017bcb6SMatthew G. Knepley     Vec         du, uhat, r, rhat, df;
1864f3c94560SMatthew G. Knepley     PetscReal   h;
1865f017bcb6SMatthew G. Knepley     PetscReal  *es, *hs, *errors;
1866f017bcb6SMatthew G. Knepley     PetscReal   hMax = 1.0, hMin = 1e-6, hMult = 0.1;
1867f017bcb6SMatthew G. Knepley     PetscInt    Nv, v;
1868f017bcb6SMatthew G. Knepley 
1869f017bcb6SMatthew G. Knepley     /* Choose a perturbation direction */
1870f017bcb6SMatthew G. Knepley     ierr = PetscRandomCreate(comm, &rand);CHKERRQ(ierr);
1871f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &du);CHKERRQ(ierr);
1872f017bcb6SMatthew G. Knepley     ierr = VecSetRandom(du, rand);CHKERRQ(ierr);
1873f017bcb6SMatthew G. Knepley     ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr);
1874f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &df);CHKERRQ(ierr);
1875f017bcb6SMatthew G. Knepley     ierr = MatMult(J, du, df);CHKERRQ(ierr);
1876f017bcb6SMatthew G. Knepley     /* Evaluate residual at u, F(u), save in vector r */
1877f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
1878f017bcb6SMatthew G. Knepley     ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr);
1879f017bcb6SMatthew G. Knepley     /* Look at the convergence of our Taylor approximation as we approach u */
1880f017bcb6SMatthew G. Knepley     for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv);
1881f017bcb6SMatthew G. Knepley     ierr = PetscCalloc3(Nv, &es, Nv, &hs, Nv, &errors);CHKERRQ(ierr);
1882f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &uhat);CHKERRQ(ierr);
1883f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &rhat);CHKERRQ(ierr);
1884f017bcb6SMatthew G. Knepley     for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv) {
1885f017bcb6SMatthew G. Knepley       ierr = VecWAXPY(uhat, h, du, u);CHKERRQ(ierr);
1886f017bcb6SMatthew G. Knepley       /* F(\hat u) \approx F(u) + J(u) (uhat - u) = F(u) + h * J(u) du */
1887f017bcb6SMatthew G. Knepley       ierr = SNESComputeFunction(snes, uhat, rhat);CHKERRQ(ierr);
1888f017bcb6SMatthew G. Knepley       ierr = VecAXPBYPCZ(rhat, -1.0, -h, 1.0, r, df);CHKERRQ(ierr);
1889f017bcb6SMatthew G. Knepley       ierr = VecNorm(rhat, NORM_2, &errors[Nv]);CHKERRQ(ierr);
1890f017bcb6SMatthew G. Knepley 
1891f017bcb6SMatthew G. Knepley       es[Nv] = PetscLog10Real(errors[Nv]);
1892f017bcb6SMatthew G. Knepley       hs[Nv] = PetscLog10Real(h);
1893f017bcb6SMatthew G. Knepley     }
1894f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&uhat);CHKERRQ(ierr);
1895f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&rhat);CHKERRQ(ierr);
1896f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&df);CHKERRQ(ierr);
18971878804aSMatthew G. Knepley     ierr = VecDestroy(&r);CHKERRQ(ierr);
1898f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&du);CHKERRQ(ierr);
1899f017bcb6SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
1900f017bcb6SMatthew G. Knepley       if ((tol >= 0) && (errors[v] > tol)) break;
1901f017bcb6SMatthew G. Knepley       else if (errors[v] > PETSC_SMALL)    break;
1902f017bcb6SMatthew G. Knepley     }
1903f3c94560SMatthew G. Knepley     if (v == Nv) isLin = PETSC_TRUE;
1904f017bcb6SMatthew G. Knepley     ierr = PetscLinearRegression(Nv, hs, es, &slope, &intercept);CHKERRQ(ierr);
1905f017bcb6SMatthew G. Knepley     ierr = PetscFree3(es, hs, errors);CHKERRQ(ierr);
1906f017bcb6SMatthew G. Knepley     /* Slope should be about 2 */
1907f017bcb6SMatthew G. Knepley     if (tol >= 0) {
1908b878532fSMatthew G. Knepley       if (!isLin && PetscAbsReal(2 - slope) > tol) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Taylor approximation convergence rate should be 2, not %0.2f", (double) slope);
1909b878532fSMatthew G. Knepley     } else if (isLinear || convRate) {
1910b878532fSMatthew G. Knepley       if (isLinear) *isLinear = isLin;
1911b878532fSMatthew G. Knepley       if (convRate) *convRate = slope;
1912f017bcb6SMatthew G. Knepley     } else {
1913f3c94560SMatthew G. Knepley       if (!isLin) {ierr = PetscPrintf(comm, "Taylor approximation converging at order %3.2f\n", (double) slope);CHKERRQ(ierr);}
1914f017bcb6SMatthew G. Knepley       else        {ierr = PetscPrintf(comm, "Function appears to be linear\n");CHKERRQ(ierr);}
1915f017bcb6SMatthew G. Knepley     }
1916f017bcb6SMatthew G. Knepley   }
19171878804aSMatthew G. Knepley   ierr = MatDestroy(&J);CHKERRQ(ierr);
19181878804aSMatthew G. Knepley   PetscFunctionReturn(0);
19191878804aSMatthew G. Knepley }
19201878804aSMatthew G. Knepley 
19217f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheck_Internal(SNES snes, DM dm, Vec u)
1922f017bcb6SMatthew G. Knepley {
1923f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1924f017bcb6SMatthew G. Knepley 
1925f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1926f2cacb80SMatthew G. Knepley   ierr = DMSNESCheckDiscretization(snes, dm, 0.0, u, -1.0, NULL);CHKERRQ(ierr);
1927f3c94560SMatthew G. Knepley   ierr = DMSNESCheckResidual(snes, dm, u, -1.0, NULL);CHKERRQ(ierr);
1928f3c94560SMatthew G. Knepley   ierr = DMSNESCheckJacobian(snes, dm, u, -1.0, NULL, NULL);CHKERRQ(ierr);
1929f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1930f017bcb6SMatthew G. Knepley }
1931f017bcb6SMatthew G. Knepley 
1932bee9a294SMatthew G. Knepley /*@C
1933bee9a294SMatthew G. Knepley   DMSNESCheckFromOptions - Check the residual and Jacobian functions using the exact solution by outputting some diagnostic information
1934bee9a294SMatthew G. Knepley 
1935bee9a294SMatthew G. Knepley   Input Parameters:
1936bee9a294SMatthew G. Knepley + snes - the SNES object
19377f96f943SMatthew G. Knepley - u    - representative SNES vector
19387f96f943SMatthew G. Knepley 
19397f96f943SMatthew G. Knepley   Note: The user must call PetscDSSetExactSolution() beforehand
1940bee9a294SMatthew G. Knepley 
1941bee9a294SMatthew G. Knepley   Level: developer
1942bee9a294SMatthew G. Knepley @*/
19437f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u)
19441878804aSMatthew G. Knepley {
19451878804aSMatthew G. Knepley   DM             dm;
19461878804aSMatthew G. Knepley   Vec            sol;
19471878804aSMatthew G. Knepley   PetscBool      check;
19481878804aSMatthew G. Knepley   PetscErrorCode ierr;
19491878804aSMatthew G. Knepley 
19501878804aSMatthew G. Knepley   PetscFunctionBegin;
1951c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr);
19521878804aSMatthew G. Knepley   if (!check) PetscFunctionReturn(0);
19531878804aSMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
19541878804aSMatthew G. Knepley   ierr = VecDuplicate(u, &sol);CHKERRQ(ierr);
19551878804aSMatthew G. Knepley   ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr);
19567f96f943SMatthew G. Knepley   ierr = DMSNESCheck_Internal(snes, dm, sol);CHKERRQ(ierr);
19571878804aSMatthew G. Knepley   ierr = VecDestroy(&sol);CHKERRQ(ierr);
1958552f7358SJed Brown   PetscFunctionReturn(0);
1959552f7358SJed Brown }
1960