xref: /petsc/src/snes/utils/dmplexsnes.c (revision 9fbee5477fd88ea4536ebb185f3c80da15fb55c0)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I "petscdmplex.h" I*/
2af0996ceSBarry Smith #include <petsc/private/snesimpl.h>     /*I "petscsnes.h"   I*/
324cdb843SMatthew G. Knepley #include <petscds.h>
4af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
5af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h>
6552f7358SJed Brown 
7649ef022SMatthew Knepley static void pressure_Private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8649ef022SMatthew Knepley                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
9649ef022SMatthew Knepley                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
10649ef022SMatthew Knepley                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar p[])
11649ef022SMatthew Knepley {
12649ef022SMatthew Knepley   p[0] = u[uOff[1]];
13649ef022SMatthew Knepley }
14649ef022SMatthew Knepley 
15649ef022SMatthew Knepley /*
16649ef022SMatthew Knepley   SNESCorrectDiscretePressure_Private - Add a vector in the nullspace to make the continuum integral of the pressure field equal to zero. This is normally used only to evaluate convergence rates for the pressure accurately.
17649ef022SMatthew Knepley 
18649ef022SMatthew Knepley   Collective on SNES
19649ef022SMatthew Knepley 
20649ef022SMatthew Knepley   Input Parameters:
21649ef022SMatthew Knepley + snes      - The SNES
22649ef022SMatthew Knepley . pfield    - The field number for pressure
23649ef022SMatthew Knepley . nullspace - The pressure nullspace
24649ef022SMatthew Knepley . u         - The solution vector
25649ef022SMatthew Knepley - ctx       - An optional user context
26649ef022SMatthew Knepley 
27649ef022SMatthew Knepley   Output Parameter:
28649ef022SMatthew Knepley . u         - The solution with a continuum pressure integral of zero
29649ef022SMatthew Knepley 
30649ef022SMatthew Knepley   Notes:
31649ef022SMatthew Knepley   If int(u) = a and int(n) = b, then int(u - a/b n) = a - a/b b = 0. We assume that the nullspace is a single vector given explicitly.
32649ef022SMatthew Knepley 
33649ef022SMatthew Knepley   Level: developer
34649ef022SMatthew Knepley 
35649ef022SMatthew Knepley .seealso: SNESConvergedCorrectPressure()
36649ef022SMatthew Knepley */
37649ef022SMatthew Knepley static PetscErrorCode SNESCorrectDiscretePressure_Private(SNES snes, PetscInt pfield, MatNullSpace nullspace, Vec u, void *ctx)
38649ef022SMatthew Knepley {
39649ef022SMatthew Knepley   DM             dm;
40649ef022SMatthew Knepley   PetscDS        ds;
41649ef022SMatthew Knepley   const Vec     *nullvecs;
42649ef022SMatthew Knepley   PetscScalar    pintd, *intc, *intn;
43649ef022SMatthew Knepley   MPI_Comm       comm;
44649ef022SMatthew Knepley   PetscInt       Nf, Nv;
45649ef022SMatthew Knepley   PetscErrorCode ierr;
46649ef022SMatthew Knepley 
47649ef022SMatthew Knepley   PetscFunctionBegin;
48649ef022SMatthew Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
49649ef022SMatthew Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
509ace16cdSJacob Faibussowitsch   PetscAssertFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a SNES DM");
519ace16cdSJacob Faibussowitsch   PetscAssertFalse(!nullspace,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a Jacobian nullspace");
52649ef022SMatthew Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
53649ef022SMatthew Knepley   ierr = PetscDSSetObjective(ds, pfield, pressure_Private);CHKERRQ(ierr);
54649ef022SMatthew Knepley   ierr = MatNullSpaceGetVecs(nullspace, NULL, &Nv, &nullvecs);CHKERRQ(ierr);
559ace16cdSJacob Faibussowitsch   PetscAssertFalse(Nv != 1,comm, PETSC_ERR_ARG_OUTOFRANGE, "Can only handle a single null vector for pressure, not %D", Nv);
56649ef022SMatthew Knepley   ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr);
579ace16cdSJacob Faibussowitsch   PetscAssertFalse(PetscAbsScalar(pintd) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Discrete integral of pressure: %g", (double) PetscRealPart(pintd));
58649ef022SMatthew Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
59649ef022SMatthew Knepley   ierr = PetscMalloc2(Nf, &intc, Nf, &intn);CHKERRQ(ierr);
60649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, nullvecs[0], intn, ctx);CHKERRQ(ierr);
61649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr);
62649ef022SMatthew Knepley   ierr = VecAXPY(u, -intc[pfield]/intn[pfield], nullvecs[0]);CHKERRQ(ierr);
63649ef022SMatthew Knepley #if defined (PETSC_USE_DEBUG)
64649ef022SMatthew Knepley   ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr);
659ace16cdSJacob Faibussowitsch   PetscAssertFalse(PetscAbsScalar(intc[pfield]) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Continuum integral of pressure after correction: %g", (double) PetscRealPart(intc[pfield]));
66649ef022SMatthew Knepley #endif
67649ef022SMatthew Knepley   ierr = PetscFree2(intc, intn);CHKERRQ(ierr);
68649ef022SMatthew Knepley   PetscFunctionReturn(0);
69649ef022SMatthew Knepley }
70649ef022SMatthew Knepley 
71649ef022SMatthew Knepley /*@C
72649ef022SMatthew Knepley    SNESConvergedCorrectPressure - Convergence test that adds a vector in the nullspace to make the continuum integral of the pressure field equal to zero. This is normally used only to evaluate convergence rates for the pressure accurately. The convergence test itself just mimics SNESConvergedDefault().
73649ef022SMatthew Knepley 
74649ef022SMatthew Knepley    Logically Collective on SNES
75649ef022SMatthew Knepley 
76649ef022SMatthew Knepley    Input Parameters:
77649ef022SMatthew Knepley +  snes - the SNES context
78649ef022SMatthew Knepley .  it - the iteration (0 indicates before any Newton steps)
79649ef022SMatthew Knepley .  xnorm - 2-norm of current iterate
80649ef022SMatthew Knepley .  snorm - 2-norm of current step
81649ef022SMatthew Knepley .  fnorm - 2-norm of function at current iterate
82649ef022SMatthew Knepley -  ctx   - Optional user context
83649ef022SMatthew Knepley 
84649ef022SMatthew Knepley    Output Parameter:
85649ef022SMatthew Knepley .  reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN
86649ef022SMatthew Knepley 
87649ef022SMatthew Knepley    Notes:
88649ef022SMatthew Knepley    In order to use this monitor, you must setup several PETSc structures. First fields must be added to the DM, and a PetscDS must be created with discretizations of those fields. We currently assume that the pressure field has index 1. The pressure field must have a nullspace, likely created using the DMSetNullSpaceConstructor() interface. Last we must be able to integrate the pressure over the domain, so the DM attached to the SNES must be a Plex at this time.
89649ef022SMatthew Knepley 
90649ef022SMatthew Knepley    Level: advanced
91649ef022SMatthew Knepley 
92649ef022SMatthew Knepley .seealso: SNESConvergedDefault(), SNESSetConvergenceTest(), DMSetNullSpaceConstructor()
93649ef022SMatthew Knepley @*/
94649ef022SMatthew Knepley PetscErrorCode SNESConvergedCorrectPressure(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *ctx)
95649ef022SMatthew Knepley {
96649ef022SMatthew Knepley   PetscBool      monitorIntegral = PETSC_FALSE;
97649ef022SMatthew Knepley   PetscErrorCode ierr;
98649ef022SMatthew Knepley 
99649ef022SMatthew Knepley   PetscFunctionBegin;
100649ef022SMatthew Knepley   ierr = SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx);CHKERRQ(ierr);
101649ef022SMatthew Knepley   if (monitorIntegral) {
102649ef022SMatthew Knepley     Mat          J;
103649ef022SMatthew Knepley     Vec          u;
104649ef022SMatthew Knepley     MatNullSpace nullspace;
105649ef022SMatthew Knepley     const Vec   *nullvecs;
106649ef022SMatthew Knepley     PetscScalar  pintd;
107649ef022SMatthew Knepley 
108649ef022SMatthew Knepley     ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr);
109649ef022SMatthew Knepley     ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr);
110649ef022SMatthew Knepley     ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
111649ef022SMatthew Knepley     ierr = MatNullSpaceGetVecs(nullspace, NULL, NULL, &nullvecs);CHKERRQ(ierr);
112649ef022SMatthew Knepley     ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr);
1137d3de750SJacob Faibussowitsch     ierr = PetscInfo(snes, "SNES: Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd));CHKERRQ(ierr);
114649ef022SMatthew Knepley   }
115649ef022SMatthew Knepley   if (*reason > 0) {
116649ef022SMatthew Knepley     Mat          J;
117649ef022SMatthew Knepley     Vec          u;
118649ef022SMatthew Knepley     MatNullSpace nullspace;
119649ef022SMatthew Knepley     PetscInt     pfield = 1;
120649ef022SMatthew Knepley 
121649ef022SMatthew Knepley     ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr);
122649ef022SMatthew Knepley     ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr);
123649ef022SMatthew Knepley     ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
124649ef022SMatthew Knepley     ierr = SNESCorrectDiscretePressure_Private(snes, pfield, nullspace, u, ctx);CHKERRQ(ierr);
125649ef022SMatthew Knepley   }
126649ef022SMatthew Knepley   PetscFunctionReturn(0);
127649ef022SMatthew Knepley }
128649ef022SMatthew Knepley 
12924cdb843SMatthew G. Knepley /************************** Interpolation *******************************/
13024cdb843SMatthew G. Knepley 
1316da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy)
1326da023fcSToby Isaac {
1336da023fcSToby Isaac   PetscBool      isPlex;
1346da023fcSToby Isaac   PetscErrorCode ierr;
1356da023fcSToby Isaac 
1366da023fcSToby Isaac   PetscFunctionBegin;
1376da023fcSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr);
1386da023fcSToby Isaac   if (isPlex) {
1396da023fcSToby Isaac     *plex = dm;
1406da023fcSToby Isaac     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
141f7148743SMatthew G. Knepley   } else {
142f7148743SMatthew G. Knepley     ierr = PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex);CHKERRQ(ierr);
143f7148743SMatthew G. Knepley     if (!*plex) {
1446da023fcSToby Isaac       ierr = DMConvert(dm,DMPLEX,plex);CHKERRQ(ierr);
145f7148743SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex);CHKERRQ(ierr);
1466da023fcSToby Isaac       if (copy) {
1476da023fcSToby Isaac         ierr = DMCopyDMSNES(dm, *plex);CHKERRQ(ierr);
1489a2a23afSMatthew G. Knepley         ierr = DMCopyAuxiliaryVec(dm, *plex);CHKERRQ(ierr);
1496da023fcSToby Isaac       }
150f7148743SMatthew G. Knepley     } else {
151f7148743SMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) *plex);CHKERRQ(ierr);
152f7148743SMatthew G. Knepley     }
1536da023fcSToby Isaac   }
1546da023fcSToby Isaac   PetscFunctionReturn(0);
1556da023fcSToby Isaac }
1566da023fcSToby Isaac 
1574267b1a3SMatthew G. Knepley /*@C
1584267b1a3SMatthew G. Knepley   DMInterpolationCreate - Creates a DMInterpolationInfo context
1594267b1a3SMatthew G. Knepley 
160d083f849SBarry Smith   Collective
1614267b1a3SMatthew G. Knepley 
1624267b1a3SMatthew G. Knepley   Input Parameter:
1634267b1a3SMatthew G. Knepley . comm - the communicator
1644267b1a3SMatthew G. Knepley 
1654267b1a3SMatthew G. Knepley   Output Parameter:
1664267b1a3SMatthew G. Knepley . ctx - the context
1674267b1a3SMatthew G. Knepley 
1684267b1a3SMatthew G. Knepley   Level: beginner
1694267b1a3SMatthew G. Knepley 
1704267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationDestroy()
1714267b1a3SMatthew G. Knepley @*/
1720adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx)
1730adebc6cSBarry Smith {
174552f7358SJed Brown   PetscErrorCode ierr;
175552f7358SJed Brown 
176552f7358SJed Brown   PetscFunctionBegin;
177552f7358SJed Brown   PetscValidPointer(ctx, 2);
17895dccacaSBarry Smith   ierr = PetscNew(ctx);CHKERRQ(ierr);
1791aa26658SKarl Rupp 
180552f7358SJed Brown   (*ctx)->comm   = comm;
181552f7358SJed Brown   (*ctx)->dim    = -1;
182552f7358SJed Brown   (*ctx)->nInput = 0;
1830298fd71SBarry Smith   (*ctx)->points = NULL;
1840298fd71SBarry Smith   (*ctx)->cells  = NULL;
185552f7358SJed Brown   (*ctx)->n      = -1;
1860298fd71SBarry Smith   (*ctx)->coords = NULL;
187552f7358SJed Brown   PetscFunctionReturn(0);
188552f7358SJed Brown }
189552f7358SJed Brown 
1904267b1a3SMatthew G. Knepley /*@C
1914267b1a3SMatthew G. Knepley   DMInterpolationSetDim - Sets the spatial dimension for the interpolation context
1924267b1a3SMatthew G. Knepley 
1934267b1a3SMatthew G. Knepley   Not collective
1944267b1a3SMatthew G. Knepley 
1954267b1a3SMatthew G. Knepley   Input Parameters:
1964267b1a3SMatthew G. Knepley + ctx - the context
1974267b1a3SMatthew G. Knepley - dim - the spatial dimension
1984267b1a3SMatthew G. Knepley 
1994267b1a3SMatthew G. Knepley   Level: intermediate
2004267b1a3SMatthew G. Knepley 
2014267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2024267b1a3SMatthew G. Knepley @*/
2030adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim)
2040adebc6cSBarry Smith {
205552f7358SJed Brown   PetscFunctionBegin;
2069ace16cdSJacob Faibussowitsch   PetscAssertFalse((dim < 1) || (dim > 3),ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %D", dim);
207552f7358SJed Brown   ctx->dim = dim;
208552f7358SJed Brown   PetscFunctionReturn(0);
209552f7358SJed Brown }
210552f7358SJed Brown 
2114267b1a3SMatthew G. Knepley /*@C
2124267b1a3SMatthew G. Knepley   DMInterpolationGetDim - Gets the spatial dimension for the interpolation context
2134267b1a3SMatthew G. Knepley 
2144267b1a3SMatthew G. Knepley   Not collective
2154267b1a3SMatthew G. Knepley 
2164267b1a3SMatthew G. Knepley   Input Parameter:
2174267b1a3SMatthew G. Knepley . ctx - the context
2184267b1a3SMatthew G. Knepley 
2194267b1a3SMatthew G. Knepley   Output Parameter:
2204267b1a3SMatthew G. Knepley . dim - the spatial dimension
2214267b1a3SMatthew G. Knepley 
2224267b1a3SMatthew G. Knepley   Level: intermediate
2234267b1a3SMatthew G. Knepley 
2244267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2254267b1a3SMatthew G. Knepley @*/
2260adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim)
2270adebc6cSBarry Smith {
228552f7358SJed Brown   PetscFunctionBegin;
229552f7358SJed Brown   PetscValidIntPointer(dim, 2);
230552f7358SJed Brown   *dim = ctx->dim;
231552f7358SJed Brown   PetscFunctionReturn(0);
232552f7358SJed Brown }
233552f7358SJed Brown 
2344267b1a3SMatthew G. Knepley /*@C
2354267b1a3SMatthew G. Knepley   DMInterpolationSetDof - Sets the number of fields interpolated at a point for the interpolation context
2364267b1a3SMatthew G. Knepley 
2374267b1a3SMatthew G. Knepley   Not collective
2384267b1a3SMatthew G. Knepley 
2394267b1a3SMatthew G. Knepley   Input Parameters:
2404267b1a3SMatthew G. Knepley + ctx - the context
2414267b1a3SMatthew G. Knepley - dof - the number of fields
2424267b1a3SMatthew G. Knepley 
2434267b1a3SMatthew G. Knepley   Level: intermediate
2444267b1a3SMatthew G. Knepley 
2454267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2464267b1a3SMatthew G. Knepley @*/
2470adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof)
2480adebc6cSBarry Smith {
249552f7358SJed Brown   PetscFunctionBegin;
2509ace16cdSJacob Faibussowitsch   PetscAssertFalse(dof < 1,ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %D", dof);
251552f7358SJed Brown   ctx->dof = dof;
252552f7358SJed Brown   PetscFunctionReturn(0);
253552f7358SJed Brown }
254552f7358SJed Brown 
2554267b1a3SMatthew G. Knepley /*@C
2564267b1a3SMatthew G. Knepley   DMInterpolationGetDof - Gets the number of fields interpolated at a point for the interpolation context
2574267b1a3SMatthew G. Knepley 
2584267b1a3SMatthew G. Knepley   Not collective
2594267b1a3SMatthew G. Knepley 
2604267b1a3SMatthew G. Knepley   Input Parameter:
2614267b1a3SMatthew G. Knepley . ctx - the context
2624267b1a3SMatthew G. Knepley 
2634267b1a3SMatthew G. Knepley   Output Parameter:
2644267b1a3SMatthew G. Knepley . dof - the number of fields
2654267b1a3SMatthew G. Knepley 
2664267b1a3SMatthew G. Knepley   Level: intermediate
2674267b1a3SMatthew G. Knepley 
2684267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints()
2694267b1a3SMatthew G. Knepley @*/
2700adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof)
2710adebc6cSBarry Smith {
272552f7358SJed Brown   PetscFunctionBegin;
273552f7358SJed Brown   PetscValidIntPointer(dof, 2);
274552f7358SJed Brown   *dof = ctx->dof;
275552f7358SJed Brown   PetscFunctionReturn(0);
276552f7358SJed Brown }
277552f7358SJed Brown 
2784267b1a3SMatthew G. Knepley /*@C
2794267b1a3SMatthew G. Knepley   DMInterpolationAddPoints - Add points at which we will interpolate the fields
2804267b1a3SMatthew G. Knepley 
2814267b1a3SMatthew G. Knepley   Not collective
2824267b1a3SMatthew G. Knepley 
2834267b1a3SMatthew G. Knepley   Input Parameters:
2844267b1a3SMatthew G. Knepley + ctx    - the context
2854267b1a3SMatthew G. Knepley . n      - the number of points
2864267b1a3SMatthew G. Knepley - points - the coordinates for each point, an array of size n * dim
2874267b1a3SMatthew G. Knepley 
2884267b1a3SMatthew G. Knepley   Note: The coordinate information is copied.
2894267b1a3SMatthew G. Knepley 
2904267b1a3SMatthew G. Knepley   Level: intermediate
2914267b1a3SMatthew G. Knepley 
2924267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationCreate()
2934267b1a3SMatthew G. Knepley @*/
2940adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[])
2950adebc6cSBarry Smith {
296552f7358SJed Brown   PetscErrorCode ierr;
297552f7358SJed Brown 
298552f7358SJed Brown   PetscFunctionBegin;
2999ace16cdSJacob Faibussowitsch   PetscAssertFalse(ctx->dim < 0,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
3009ace16cdSJacob Faibussowitsch   PetscAssertFalse(ctx->points,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet");
301552f7358SJed Brown   ctx->nInput = n;
3021aa26658SKarl Rupp 
303785e854fSJed Brown   ierr = PetscMalloc1(n*ctx->dim, &ctx->points);CHKERRQ(ierr);
304580bdb30SBarry Smith   ierr = PetscArraycpy(ctx->points, points, n*ctx->dim);CHKERRQ(ierr);
305552f7358SJed Brown   PetscFunctionReturn(0);
306552f7358SJed Brown }
307552f7358SJed Brown 
3084267b1a3SMatthew G. Knepley /*@C
30952aa1562SMatthew G. Knepley   DMInterpolationSetUp - Compute spatial indices for point location during interpolation
3104267b1a3SMatthew G. Knepley 
3114267b1a3SMatthew G. Knepley   Collective on ctx
3124267b1a3SMatthew G. Knepley 
3134267b1a3SMatthew G. Knepley   Input Parameters:
3144267b1a3SMatthew G. Knepley + ctx - the context
3154267b1a3SMatthew G. Knepley . dm  - the DM for the function space used for interpolation
31652aa1562SMatthew G. Knepley . redundantPoints - If PETSC_TRUE, all processes are passing in the same array of points. Otherwise, points need to be communicated among processes.
3177deeda50SSatish Balay - ignoreOutsideDomain - If PETSC_TRUE, ignore points outside the domain, otherwise return an error
3184267b1a3SMatthew G. Knepley 
3194267b1a3SMatthew G. Knepley   Level: intermediate
3204267b1a3SMatthew G. Knepley 
3214267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
3224267b1a3SMatthew G. Knepley @*/
32352aa1562SMatthew G. Knepley PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints, PetscBool ignoreOutsideDomain)
3240adebc6cSBarry Smith {
325552f7358SJed Brown   MPI_Comm          comm = ctx->comm;
326552f7358SJed Brown   PetscScalar       *a;
327552f7358SJed Brown   PetscInt          p, q, i;
328552f7358SJed Brown   PetscMPIInt       rank, size;
329552f7358SJed Brown   PetscErrorCode    ierr;
330552f7358SJed Brown   Vec               pointVec;
3313a93e3b7SToby Isaac   PetscSF           cellSF;
332552f7358SJed Brown   PetscLayout       layout;
333552f7358SJed Brown   PetscReal         *globalPoints;
334cb313848SJed Brown   PetscScalar       *globalPointsScalar;
335552f7358SJed Brown   const PetscInt    *ranges;
336552f7358SJed Brown   PetscMPIInt       *counts, *displs;
3373a93e3b7SToby Isaac   const PetscSFNode *foundCells;
3383a93e3b7SToby Isaac   const PetscInt    *foundPoints;
339552f7358SJed Brown   PetscMPIInt       *foundProcs, *globalProcs;
3403a93e3b7SToby Isaac   PetscInt          n, N, numFound;
341552f7358SJed Brown 
34219436ca2SJed Brown   PetscFunctionBegin;
343064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
344ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
345ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
3469ace16cdSJacob Faibussowitsch   PetscAssertFalse(ctx->dim < 0,comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set");
34719436ca2SJed Brown   /* Locate points */
34819436ca2SJed Brown   n = ctx->nInput;
349552f7358SJed Brown   if (!redundantPoints) {
350552f7358SJed Brown     ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
351552f7358SJed Brown     ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
352552f7358SJed Brown     ierr = PetscLayoutSetLocalSize(layout, n);CHKERRQ(ierr);
353552f7358SJed Brown     ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
354552f7358SJed Brown     ierr = PetscLayoutGetSize(layout, &N);CHKERRQ(ierr);
355552f7358SJed Brown     /* Communicate all points to all processes */
356dcca6d9dSJed Brown     ierr = PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs);CHKERRQ(ierr);
357552f7358SJed Brown     ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
358552f7358SJed Brown     for (p = 0; p < size; ++p) {
359552f7358SJed Brown       counts[p] = (ranges[p+1] - ranges[p])*ctx->dim;
360552f7358SJed Brown       displs[p] = ranges[p]*ctx->dim;
361552f7358SJed Brown     }
362ffc4695bSBarry Smith     ierr = MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm);CHKERRMPI(ierr);
363552f7358SJed Brown   } else {
364552f7358SJed Brown     N = n;
365552f7358SJed Brown     globalPoints = ctx->points;
36638ea73c8SJed Brown     counts = displs = NULL;
36738ea73c8SJed Brown     layout = NULL;
368552f7358SJed Brown   }
369552f7358SJed Brown #if 0
370dcca6d9dSJed Brown   ierr = PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
37119436ca2SJed Brown   /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */
372552f7358SJed Brown #else
373cb313848SJed Brown #if defined(PETSC_USE_COMPLEX)
37446b3086cSToby Isaac   ierr = PetscMalloc1(N*ctx->dim,&globalPointsScalar);CHKERRQ(ierr);
37546b3086cSToby Isaac   for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i];
376cb313848SJed Brown #else
377cb313848SJed Brown   globalPointsScalar = globalPoints;
378cb313848SJed Brown #endif
37904706141SMatthew G Knepley   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec);CHKERRQ(ierr);
380dcca6d9dSJed Brown   ierr = PetscMalloc2(N,&foundProcs,N,&globalProcs);CHKERRQ(ierr);
3817b5f2079SMatthew G. Knepley   for (p = 0; p < N; ++p) {foundProcs[p] = size;}
3823a93e3b7SToby Isaac   cellSF = NULL;
3832d1fa6caSMatthew G. Knepley   ierr = DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF);CHKERRQ(ierr);
3843a93e3b7SToby Isaac   ierr = PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells);CHKERRQ(ierr);
385552f7358SJed Brown #endif
3863a93e3b7SToby Isaac   for (p = 0; p < numFound; ++p) {
3873a93e3b7SToby Isaac     if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank;
388552f7358SJed Brown   }
389552f7358SJed Brown   /* Let the lowest rank process own each point */
390820f2d46SBarry Smith   ierr   = MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm);CHKERRMPI(ierr);
391552f7358SJed Brown   ctx->n = 0;
392552f7358SJed Brown   for (p = 0; p < N; ++p) {
39352aa1562SMatthew G. Knepley     if (globalProcs[p] == size) {
3949ace16cdSJacob Faibussowitsch       PetscAssertFalse(!ignoreOutsideDomain,comm, PETSC_ERR_PLIB, "Point %d: %g %g %g not located in mesh", p, (double)globalPoints[p*ctx->dim+0], (double)(ctx->dim > 1 ? globalPoints[p*ctx->dim+1] : 0.0), (double)(ctx->dim > 2 ? globalPoints[p*ctx->dim+2] : 0.0));
395dd400576SPatrick Sanan       else if (rank == 0) ++ctx->n;
39652aa1562SMatthew G. Knepley     } else if (globalProcs[p] == rank) ++ctx->n;
397552f7358SJed Brown   }
398552f7358SJed Brown   /* Create coordinates vector and array of owned cells */
399785e854fSJed Brown   ierr = PetscMalloc1(ctx->n, &ctx->cells);CHKERRQ(ierr);
400552f7358SJed Brown   ierr = VecCreate(comm, &ctx->coords);CHKERRQ(ierr);
401552f7358SJed Brown   ierr = VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE);CHKERRQ(ierr);
402552f7358SJed Brown   ierr = VecSetBlockSize(ctx->coords, ctx->dim);CHKERRQ(ierr);
403c0dedaeaSBarry Smith   ierr = VecSetType(ctx->coords,VECSTANDARD);CHKERRQ(ierr);
404552f7358SJed Brown   ierr = VecGetArray(ctx->coords, &a);CHKERRQ(ierr);
405552f7358SJed Brown   for (p = 0, q = 0, i = 0; p < N; ++p) {
406552f7358SJed Brown     if (globalProcs[p] == rank) {
407552f7358SJed Brown       PetscInt d;
408552f7358SJed Brown 
4091aa26658SKarl Rupp       for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d];
410f317b747SMatthew G. Knepley       ctx->cells[q] = foundCells[q].index;
411f317b747SMatthew G. Knepley       ++q;
412552f7358SJed Brown     }
413dd400576SPatrick Sanan     if (globalProcs[p] == size && rank == 0) {
41452aa1562SMatthew G. Knepley       PetscInt d;
41552aa1562SMatthew G. Knepley 
41652aa1562SMatthew G. Knepley       for (d = 0; d < ctx->dim; ++d, ++i) a[i] = 0.;
41752aa1562SMatthew G. Knepley       ctx->cells[q] = -1;
41852aa1562SMatthew G. Knepley       ++q;
41952aa1562SMatthew G. Knepley     }
420552f7358SJed Brown   }
421552f7358SJed Brown   ierr = VecRestoreArray(ctx->coords, &a);CHKERRQ(ierr);
422552f7358SJed Brown #if 0
423552f7358SJed Brown   ierr = PetscFree3(foundCells,foundProcs,globalProcs);CHKERRQ(ierr);
424552f7358SJed Brown #else
425552f7358SJed Brown   ierr = PetscFree2(foundProcs,globalProcs);CHKERRQ(ierr);
4263a93e3b7SToby Isaac   ierr = PetscSFDestroy(&cellSF);CHKERRQ(ierr);
427552f7358SJed Brown   ierr = VecDestroy(&pointVec);CHKERRQ(ierr);
428552f7358SJed Brown #endif
429cb313848SJed Brown   if ((void*)globalPointsScalar != (void*)globalPoints) {ierr = PetscFree(globalPointsScalar);CHKERRQ(ierr);}
430d343d804SMatthew G. Knepley   if (!redundantPoints) {ierr = PetscFree3(globalPoints,counts,displs);CHKERRQ(ierr);}
431552f7358SJed Brown   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
432552f7358SJed Brown   PetscFunctionReturn(0);
433552f7358SJed Brown }
434552f7358SJed Brown 
4354267b1a3SMatthew G. Knepley /*@C
4364267b1a3SMatthew G. Knepley   DMInterpolationGetCoordinates - Gets a Vec with the coordinates of each interpolation point
4374267b1a3SMatthew G. Knepley 
4384267b1a3SMatthew G. Knepley   Collective on ctx
4394267b1a3SMatthew G. Knepley 
4404267b1a3SMatthew G. Knepley   Input Parameter:
4414267b1a3SMatthew G. Knepley . ctx - the context
4424267b1a3SMatthew G. Knepley 
4434267b1a3SMatthew G. Knepley   Output Parameter:
4444267b1a3SMatthew G. Knepley . coordinates  - the coordinates of interpolation points
4454267b1a3SMatthew G. Knepley 
4464267b1a3SMatthew G. Knepley   Note: The local vector entries correspond to interpolation points lying on this process, according to the associated DM. This is a borrowed vector that the user should not destroy.
4474267b1a3SMatthew G. Knepley 
4484267b1a3SMatthew G. Knepley   Level: intermediate
4494267b1a3SMatthew G. Knepley 
4504267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
4514267b1a3SMatthew G. Knepley @*/
4520adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates)
4530adebc6cSBarry Smith {
454552f7358SJed Brown   PetscFunctionBegin;
455552f7358SJed Brown   PetscValidPointer(coordinates, 2);
4569ace16cdSJacob Faibussowitsch   PetscAssertFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
457552f7358SJed Brown   *coordinates = ctx->coords;
458552f7358SJed Brown   PetscFunctionReturn(0);
459552f7358SJed Brown }
460552f7358SJed Brown 
4614267b1a3SMatthew G. Knepley /*@C
4624267b1a3SMatthew G. Knepley   DMInterpolationGetVector - Gets a Vec which can hold all the interpolated field values
4634267b1a3SMatthew G. Knepley 
4644267b1a3SMatthew G. Knepley   Collective on ctx
4654267b1a3SMatthew G. Knepley 
4664267b1a3SMatthew G. Knepley   Input Parameter:
4674267b1a3SMatthew G. Knepley . ctx - the context
4684267b1a3SMatthew G. Knepley 
4694267b1a3SMatthew G. Knepley   Output Parameter:
4704267b1a3SMatthew G. Knepley . v  - a vector capable of holding the interpolated field values
4714267b1a3SMatthew G. Knepley 
4724267b1a3SMatthew G. Knepley   Note: This vector should be returned using DMInterpolationRestoreVector().
4734267b1a3SMatthew G. Knepley 
4744267b1a3SMatthew G. Knepley   Level: intermediate
4754267b1a3SMatthew G. Knepley 
4764267b1a3SMatthew G. Knepley .seealso: DMInterpolationRestoreVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
4774267b1a3SMatthew G. Knepley @*/
4780adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v)
4790adebc6cSBarry Smith {
480552f7358SJed Brown   PetscErrorCode ierr;
481552f7358SJed Brown 
482552f7358SJed Brown   PetscFunctionBegin;
483552f7358SJed Brown   PetscValidPointer(v, 2);
4849ace16cdSJacob Faibussowitsch   PetscAssertFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
485552f7358SJed Brown   ierr = VecCreate(ctx->comm, v);CHKERRQ(ierr);
486552f7358SJed Brown   ierr = VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE);CHKERRQ(ierr);
487552f7358SJed Brown   ierr = VecSetBlockSize(*v, ctx->dof);CHKERRQ(ierr);
488c0dedaeaSBarry Smith   ierr = VecSetType(*v,VECSTANDARD);CHKERRQ(ierr);
489552f7358SJed Brown   PetscFunctionReturn(0);
490552f7358SJed Brown }
491552f7358SJed Brown 
4924267b1a3SMatthew G. Knepley /*@C
4934267b1a3SMatthew G. Knepley   DMInterpolationRestoreVector - Returns a Vec which can hold all the interpolated field values
4944267b1a3SMatthew G. Knepley 
4954267b1a3SMatthew G. Knepley   Collective on ctx
4964267b1a3SMatthew G. Knepley 
4974267b1a3SMatthew G. Knepley   Input Parameters:
4984267b1a3SMatthew G. Knepley + ctx - the context
4994267b1a3SMatthew G. Knepley - v  - a vector capable of holding the interpolated field values
5004267b1a3SMatthew G. Knepley 
5014267b1a3SMatthew G. Knepley   Level: intermediate
5024267b1a3SMatthew G. Knepley 
5034267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
5044267b1a3SMatthew G. Knepley @*/
5050adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v)
5060adebc6cSBarry Smith {
507552f7358SJed Brown   PetscErrorCode ierr;
508552f7358SJed Brown 
509552f7358SJed Brown   PetscFunctionBegin;
510552f7358SJed Brown   PetscValidPointer(v, 2);
5119ace16cdSJacob Faibussowitsch   PetscAssertFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup.");
512552f7358SJed Brown   ierr = VecDestroy(v);CHKERRQ(ierr);
513552f7358SJed Brown   PetscFunctionReturn(0);
514552f7358SJed Brown }
515552f7358SJed Brown 
516*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
517a6dfd86eSKarl Rupp {
518552f7358SJed Brown   PetscReal      *v0, *J, *invJ, detJ;
51956044e6dSMatthew G. Knepley   const PetscScalar *coords;
52056044e6dSMatthew G. Knepley   PetscScalar    *a;
521552f7358SJed Brown   PetscInt       p;
522552f7358SJed Brown   PetscErrorCode ierr;
523552f7358SJed Brown 
524552f7358SJed Brown   PetscFunctionBegin;
525dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
52656044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
527552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
528552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
529552f7358SJed Brown     PetscInt     c = ctx->cells[p];
530a1e44745SMatthew G. Knepley     PetscScalar *x = NULL;
531552f7358SJed Brown     PetscReal    xi[4];
532552f7358SJed Brown     PetscInt     d, f, comp;
533552f7358SJed Brown 
5348e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
5359ace16cdSJacob Faibussowitsch     PetscAssertFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c);
5360298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
5371aa26658SKarl Rupp     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
5381aa26658SKarl Rupp 
539552f7358SJed Brown     for (d = 0; d < ctx->dim; ++d) {
540552f7358SJed Brown       xi[d] = 0.0;
5411aa26658SKarl 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]);
5421aa26658SKarl 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];
543552f7358SJed Brown     }
5440298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
545552f7358SJed Brown   }
546552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
54756044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
548552f7358SJed Brown   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
549552f7358SJed Brown   PetscFunctionReturn(0);
550552f7358SJed Brown }
551552f7358SJed Brown 
552*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
5537a1931ceSMatthew G. Knepley {
5547a1931ceSMatthew G. Knepley   PetscReal      *v0, *J, *invJ, detJ;
55556044e6dSMatthew G. Knepley   const PetscScalar *coords;
55656044e6dSMatthew G. Knepley   PetscScalar    *a;
5577a1931ceSMatthew G. Knepley   PetscInt       p;
5587a1931ceSMatthew G. Knepley   PetscErrorCode ierr;
5597a1931ceSMatthew G. Knepley 
5607a1931ceSMatthew G. Knepley   PetscFunctionBegin;
561dcca6d9dSJed Brown   ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr);
56256044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
5637a1931ceSMatthew G. Knepley   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
5647a1931ceSMatthew G. Knepley   for (p = 0; p < ctx->n; ++p) {
5657a1931ceSMatthew G. Knepley     PetscInt       c = ctx->cells[p];
5667a1931ceSMatthew G. Knepley     const PetscInt order[3] = {2, 1, 3};
5672584bbe8SMatthew G. Knepley     PetscScalar   *x = NULL;
5687a1931ceSMatthew G. Knepley     PetscReal      xi[4];
5697a1931ceSMatthew G. Knepley     PetscInt       d, f, comp;
5707a1931ceSMatthew G. Knepley 
5718e0841e0SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
5729ace16cdSJacob Faibussowitsch     PetscAssertFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c);
5737a1931ceSMatthew G. Knepley     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
5747a1931ceSMatthew G. Knepley     for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp];
5757a1931ceSMatthew G. Knepley 
5767a1931ceSMatthew G. Knepley     for (d = 0; d < ctx->dim; ++d) {
5777a1931ceSMatthew G. Knepley       xi[d] = 0.0;
5787a1931ceSMatthew 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]);
5797a1931ceSMatthew 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];
5807a1931ceSMatthew G. Knepley     }
5817a1931ceSMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr);
5827a1931ceSMatthew G. Knepley   }
5837a1931ceSMatthew G. Knepley   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
58456044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
5857a1931ceSMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
5867a1931ceSMatthew G. Knepley   PetscFunctionReturn(0);
5877a1931ceSMatthew G. Knepley }
5887a1931ceSMatthew G. Knepley 
589*9fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
590552f7358SJed Brown {
591552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
592552f7358SJed Brown   const PetscScalar x0        = vertices[0];
593552f7358SJed Brown   const PetscScalar y0        = vertices[1];
594552f7358SJed Brown   const PetscScalar x1        = vertices[2];
595552f7358SJed Brown   const PetscScalar y1        = vertices[3];
596552f7358SJed Brown   const PetscScalar x2        = vertices[4];
597552f7358SJed Brown   const PetscScalar y2        = vertices[5];
598552f7358SJed Brown   const PetscScalar x3        = vertices[6];
599552f7358SJed Brown   const PetscScalar y3        = vertices[7];
600552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
601552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
602552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
603552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
604552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
605552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
60656044e6dSMatthew G. Knepley   const PetscScalar *ref;
60756044e6dSMatthew G. Knepley   PetscScalar       *real;
608552f7358SJed Brown   PetscErrorCode    ierr;
609552f7358SJed Brown 
610552f7358SJed Brown   PetscFunctionBegin;
61156044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
612552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
613552f7358SJed Brown   {
614552f7358SJed Brown     const PetscScalar p0 = ref[0];
615552f7358SJed Brown     const PetscScalar p1 = ref[1];
616552f7358SJed Brown 
617552f7358SJed Brown     real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1;
618552f7358SJed Brown     real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1;
619552f7358SJed Brown   }
620552f7358SJed Brown   ierr = PetscLogFlops(28);CHKERRQ(ierr);
62156044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
622552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
623552f7358SJed Brown   PetscFunctionReturn(0);
624552f7358SJed Brown }
625552f7358SJed Brown 
626af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
627*9fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
628552f7358SJed Brown {
629552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
630552f7358SJed Brown   const PetscScalar x0        = vertices[0];
631552f7358SJed Brown   const PetscScalar y0        = vertices[1];
632552f7358SJed Brown   const PetscScalar x1        = vertices[2];
633552f7358SJed Brown   const PetscScalar y1        = vertices[3];
634552f7358SJed Brown   const PetscScalar x2        = vertices[4];
635552f7358SJed Brown   const PetscScalar y2        = vertices[5];
636552f7358SJed Brown   const PetscScalar x3        = vertices[6];
637552f7358SJed Brown   const PetscScalar y3        = vertices[7];
638552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
639552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
64056044e6dSMatthew G. Knepley   const PetscScalar *ref;
641552f7358SJed Brown   PetscErrorCode    ierr;
642552f7358SJed Brown 
643552f7358SJed Brown   PetscFunctionBegin;
64456044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
645552f7358SJed Brown   {
646552f7358SJed Brown     const PetscScalar x       = ref[0];
647552f7358SJed Brown     const PetscScalar y       = ref[1];
648552f7358SJed Brown     const PetscInt    rows[2] = {0, 1};
649da80777bSKarl Rupp     PetscScalar       values[4];
650da80777bSKarl Rupp 
651da80777bSKarl Rupp     values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5;
652da80777bSKarl Rupp     values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5;
65394ab13aaSBarry Smith     ierr      = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr);
654552f7358SJed Brown   }
655552f7358SJed Brown   ierr = PetscLogFlops(30);CHKERRQ(ierr);
65656044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
65794ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65894ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
659552f7358SJed Brown   PetscFunctionReturn(0);
660552f7358SJed Brown }
661552f7358SJed Brown 
662*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
663a6dfd86eSKarl Rupp {
664fafc0619SMatthew G Knepley   DM                 dmCoord;
665de73a395SMatthew G. Knepley   PetscFE            fem = NULL;
666552f7358SJed Brown   SNES               snes;
667552f7358SJed Brown   KSP                ksp;
668552f7358SJed Brown   PC                 pc;
669552f7358SJed Brown   Vec                coordsLocal, r, ref, real;
670552f7358SJed Brown   Mat                J;
671716009bfSMatthew G. Knepley   PetscTabulation    T = NULL;
67256044e6dSMatthew G. Knepley   const PetscScalar *coords;
67356044e6dSMatthew G. Knepley   PetscScalar        *a;
674716009bfSMatthew G. Knepley   PetscReal          xir[2] = {0., 0.};
675de73a395SMatthew G. Knepley   PetscInt           Nf, p;
6765509d985SMatthew G. Knepley   const PetscInt     dof = ctx->dof;
677552f7358SJed Brown   PetscErrorCode     ierr;
678552f7358SJed Brown 
679552f7358SJed Brown   PetscFunctionBegin;
680de73a395SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
681716009bfSMatthew G. Knepley   if (Nf) {
682716009bfSMatthew G. Knepley     ierr = DMGetField(dm, 0, NULL, (PetscObject *) &fem);CHKERRQ(ierr);
683716009bfSMatthew G. Knepley     ierr = PetscFECreateTabulation(fem, 1, 1, xir, 0, &T);CHKERRQ(ierr);
684716009bfSMatthew G. Knepley   }
685552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
686fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
687552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
688552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr);
689552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
690552f7358SJed Brown   ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr);
691c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
692552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
693552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
694552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
695552f7358SJed Brown   ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr);
696552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
697552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
6980298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr);
6990298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr);
700552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
701552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
702552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
703552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
704552f7358SJed Brown 
70556044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
706552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
707552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
708a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
709552f7358SJed Brown     PetscScalar *xi;
710552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
711552f7358SJed Brown 
712552f7358SJed Brown     /* Can make this do all points at once */
7130298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
7149ace16cdSJacob Faibussowitsch     PetscAssertFalse(4*2 != coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 4*2);
7150298fd71SBarry Smith     ierr   = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
7163ec1f749SStefano Zampini     ierr   = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr);
7173ec1f749SStefano Zampini     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr);
718552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
719552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
720552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
721552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
722552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
723552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
724cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
725cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
7265509d985SMatthew G. Knepley     if (4*dof != xSize) {
7275509d985SMatthew G. Knepley       PetscInt d;
7281aa26658SKarl Rupp 
7299ace16cdSJacob Faibussowitsch       PetscAssert(fem, ctx->comm, PETSC_ERR_ARG_WRONG, "Cannot have a higher order interpolant if the discretization is not PetscFE");
7305509d985SMatthew G. Knepley       xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0;
731ef0bb6c7SMatthew G. Knepley       ierr = PetscFEComputeTabulation(fem, 1, xir, 0, T);CHKERRQ(ierr);
7325509d985SMatthew G. Knepley       for (comp = 0; comp < dof; ++comp) {
7335509d985SMatthew G. Knepley         a[p*dof+comp] = 0.0;
7345509d985SMatthew G. Knepley         for (d = 0; d < xSize/dof; ++d) {
735ef0bb6c7SMatthew G. Knepley           a[p*dof+comp] += x[d*dof+comp]*T->T[0][d*dof+comp];
7365509d985SMatthew G. Knepley         }
7375509d985SMatthew G. Knepley       }
7385509d985SMatthew G. Knepley     } else {
7395509d985SMatthew G. Knepley       for (comp = 0; comp < dof; ++comp)
7405509d985SMatthew 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];
7415509d985SMatthew G. Knepley     }
742552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
7430298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
7440298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
745552f7358SJed Brown   }
746ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr);
747552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
74856044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
749552f7358SJed Brown 
750552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
751552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
752552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
753552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
754552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
755552f7358SJed Brown   PetscFunctionReturn(0);
756552f7358SJed Brown }
757552f7358SJed Brown 
758*9fbee547SJacob Faibussowitsch static inline PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx)
759552f7358SJed Brown {
760552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
761552f7358SJed Brown   const PetscScalar x0        = vertices[0];
762552f7358SJed Brown   const PetscScalar y0        = vertices[1];
763552f7358SJed Brown   const PetscScalar z0        = vertices[2];
7647a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
7657a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
7667a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
767552f7358SJed Brown   const PetscScalar x2        = vertices[6];
768552f7358SJed Brown   const PetscScalar y2        = vertices[7];
769552f7358SJed Brown   const PetscScalar z2        = vertices[8];
7707a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
7717a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
7727a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
773552f7358SJed Brown   const PetscScalar x4        = vertices[12];
774552f7358SJed Brown   const PetscScalar y4        = vertices[13];
775552f7358SJed Brown   const PetscScalar z4        = vertices[14];
776552f7358SJed Brown   const PetscScalar x5        = vertices[15];
777552f7358SJed Brown   const PetscScalar y5        = vertices[16];
778552f7358SJed Brown   const PetscScalar z5        = vertices[17];
779552f7358SJed Brown   const PetscScalar x6        = vertices[18];
780552f7358SJed Brown   const PetscScalar y6        = vertices[19];
781552f7358SJed Brown   const PetscScalar z6        = vertices[20];
782552f7358SJed Brown   const PetscScalar x7        = vertices[21];
783552f7358SJed Brown   const PetscScalar y7        = vertices[22];
784552f7358SJed Brown   const PetscScalar z7        = vertices[23];
785552f7358SJed Brown   const PetscScalar f_1       = x1 - x0;
786552f7358SJed Brown   const PetscScalar g_1       = y1 - y0;
787552f7358SJed Brown   const PetscScalar h_1       = z1 - z0;
788552f7358SJed Brown   const PetscScalar f_3       = x3 - x0;
789552f7358SJed Brown   const PetscScalar g_3       = y3 - y0;
790552f7358SJed Brown   const PetscScalar h_3       = z3 - z0;
791552f7358SJed Brown   const PetscScalar f_4       = x4 - x0;
792552f7358SJed Brown   const PetscScalar g_4       = y4 - y0;
793552f7358SJed Brown   const PetscScalar h_4       = z4 - z0;
794552f7358SJed Brown   const PetscScalar f_01      = x2 - x1 - x3 + x0;
795552f7358SJed Brown   const PetscScalar g_01      = y2 - y1 - y3 + y0;
796552f7358SJed Brown   const PetscScalar h_01      = z2 - z1 - z3 + z0;
797552f7358SJed Brown   const PetscScalar f_12      = x7 - x3 - x4 + x0;
798552f7358SJed Brown   const PetscScalar g_12      = y7 - y3 - y4 + y0;
799552f7358SJed Brown   const PetscScalar h_12      = z7 - z3 - z4 + z0;
800552f7358SJed Brown   const PetscScalar f_02      = x5 - x1 - x4 + x0;
801552f7358SJed Brown   const PetscScalar g_02      = y5 - y1 - y4 + y0;
802552f7358SJed Brown   const PetscScalar h_02      = z5 - z1 - z4 + z0;
803552f7358SJed Brown   const PetscScalar f_012     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
804552f7358SJed Brown   const PetscScalar g_012     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
805552f7358SJed Brown   const PetscScalar h_012     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
80656044e6dSMatthew G. Knepley   const PetscScalar *ref;
80756044e6dSMatthew G. Knepley   PetscScalar       *real;
808552f7358SJed Brown   PetscErrorCode    ierr;
809552f7358SJed Brown 
810552f7358SJed Brown   PetscFunctionBegin;
81156044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
812552f7358SJed Brown   ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr);
813552f7358SJed Brown   {
814552f7358SJed Brown     const PetscScalar p0 = ref[0];
815552f7358SJed Brown     const PetscScalar p1 = ref[1];
816552f7358SJed Brown     const PetscScalar p2 = ref[2];
817552f7358SJed Brown 
818552f7358SJed 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;
819552f7358SJed 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;
820552f7358SJed 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;
821552f7358SJed Brown   }
822552f7358SJed Brown   ierr = PetscLogFlops(114);CHKERRQ(ierr);
82356044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
824552f7358SJed Brown   ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr);
825552f7358SJed Brown   PetscFunctionReturn(0);
826552f7358SJed Brown }
827552f7358SJed Brown 
828*9fbee547SJacob Faibussowitsch static inline PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx)
829552f7358SJed Brown {
830552f7358SJed Brown   const PetscScalar *vertices = (const PetscScalar*) ctx;
831552f7358SJed Brown   const PetscScalar x0        = vertices[0];
832552f7358SJed Brown   const PetscScalar y0        = vertices[1];
833552f7358SJed Brown   const PetscScalar z0        = vertices[2];
8347a1931ceSMatthew G. Knepley   const PetscScalar x1        = vertices[9];
8357a1931ceSMatthew G. Knepley   const PetscScalar y1        = vertices[10];
8367a1931ceSMatthew G. Knepley   const PetscScalar z1        = vertices[11];
837552f7358SJed Brown   const PetscScalar x2        = vertices[6];
838552f7358SJed Brown   const PetscScalar y2        = vertices[7];
839552f7358SJed Brown   const PetscScalar z2        = vertices[8];
8407a1931ceSMatthew G. Knepley   const PetscScalar x3        = vertices[3];
8417a1931ceSMatthew G. Knepley   const PetscScalar y3        = vertices[4];
8427a1931ceSMatthew G. Knepley   const PetscScalar z3        = vertices[5];
843552f7358SJed Brown   const PetscScalar x4        = vertices[12];
844552f7358SJed Brown   const PetscScalar y4        = vertices[13];
845552f7358SJed Brown   const PetscScalar z4        = vertices[14];
846552f7358SJed Brown   const PetscScalar x5        = vertices[15];
847552f7358SJed Brown   const PetscScalar y5        = vertices[16];
848552f7358SJed Brown   const PetscScalar z5        = vertices[17];
849552f7358SJed Brown   const PetscScalar x6        = vertices[18];
850552f7358SJed Brown   const PetscScalar y6        = vertices[19];
851552f7358SJed Brown   const PetscScalar z6        = vertices[20];
852552f7358SJed Brown   const PetscScalar x7        = vertices[21];
853552f7358SJed Brown   const PetscScalar y7        = vertices[22];
854552f7358SJed Brown   const PetscScalar z7        = vertices[23];
855552f7358SJed Brown   const PetscScalar f_xy      = x2 - x1 - x3 + x0;
856552f7358SJed Brown   const PetscScalar g_xy      = y2 - y1 - y3 + y0;
857552f7358SJed Brown   const PetscScalar h_xy      = z2 - z1 - z3 + z0;
858552f7358SJed Brown   const PetscScalar f_yz      = x7 - x3 - x4 + x0;
859552f7358SJed Brown   const PetscScalar g_yz      = y7 - y3 - y4 + y0;
860552f7358SJed Brown   const PetscScalar h_yz      = z7 - z3 - z4 + z0;
861552f7358SJed Brown   const PetscScalar f_xz      = x5 - x1 - x4 + x0;
862552f7358SJed Brown   const PetscScalar g_xz      = y5 - y1 - y4 + y0;
863552f7358SJed Brown   const PetscScalar h_xz      = z5 - z1 - z4 + z0;
864552f7358SJed Brown   const PetscScalar f_xyz     = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7;
865552f7358SJed Brown   const PetscScalar g_xyz     = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7;
866552f7358SJed Brown   const PetscScalar h_xyz     = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7;
86756044e6dSMatthew G. Knepley   const PetscScalar *ref;
868552f7358SJed Brown   PetscErrorCode    ierr;
869552f7358SJed Brown 
870552f7358SJed Brown   PetscFunctionBegin;
87156044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(Xref,  &ref);CHKERRQ(ierr);
872552f7358SJed Brown   {
873552f7358SJed Brown     const PetscScalar x       = ref[0];
874552f7358SJed Brown     const PetscScalar y       = ref[1];
875552f7358SJed Brown     const PetscScalar z       = ref[2];
876552f7358SJed Brown     const PetscInt    rows[3] = {0, 1, 2};
877da80777bSKarl Rupp     PetscScalar       values[9];
878da80777bSKarl Rupp 
879da80777bSKarl Rupp     values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0;
880da80777bSKarl Rupp     values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0;
881da80777bSKarl Rupp     values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0;
882da80777bSKarl Rupp     values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0;
883da80777bSKarl Rupp     values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0;
884da80777bSKarl Rupp     values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0;
885da80777bSKarl Rupp     values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0;
886da80777bSKarl Rupp     values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0;
887da80777bSKarl Rupp     values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0;
8881aa26658SKarl Rupp 
88994ab13aaSBarry Smith     ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr);
890552f7358SJed Brown   }
891552f7358SJed Brown   ierr = PetscLogFlops(152);CHKERRQ(ierr);
89256044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(Xref,  &ref);CHKERRQ(ierr);
89394ab13aaSBarry Smith   ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
89494ab13aaSBarry Smith   ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
895552f7358SJed Brown   PetscFunctionReturn(0);
896552f7358SJed Brown }
897552f7358SJed Brown 
898*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v)
899a6dfd86eSKarl Rupp {
900fafc0619SMatthew G Knepley   DM             dmCoord;
901552f7358SJed Brown   SNES           snes;
902552f7358SJed Brown   KSP            ksp;
903552f7358SJed Brown   PC             pc;
904552f7358SJed Brown   Vec            coordsLocal, r, ref, real;
905552f7358SJed Brown   Mat            J;
90656044e6dSMatthew G. Knepley   const PetscScalar *coords;
90756044e6dSMatthew G. Knepley   PetscScalar    *a;
908552f7358SJed Brown   PetscInt       p;
909552f7358SJed Brown   PetscErrorCode ierr;
910552f7358SJed Brown 
911552f7358SJed Brown   PetscFunctionBegin;
912552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
913fafc0619SMatthew G Knepley   ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr);
914552f7358SJed Brown   ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr);
915552f7358SJed Brown   ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr);
916552f7358SJed Brown   ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr);
917552f7358SJed Brown   ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr);
918c0dedaeaSBarry Smith   ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr);
919552f7358SJed Brown   ierr = VecDuplicate(r, &ref);CHKERRQ(ierr);
920552f7358SJed Brown   ierr = VecDuplicate(r, &real);CHKERRQ(ierr);
921552f7358SJed Brown   ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr);
922552f7358SJed Brown   ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr);
923552f7358SJed Brown   ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr);
924552f7358SJed Brown   ierr = MatSetUp(J);CHKERRQ(ierr);
9250298fd71SBarry Smith   ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr);
9260298fd71SBarry Smith   ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr);
927552f7358SJed Brown   ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
928552f7358SJed Brown   ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
929552f7358SJed Brown   ierr = PCSetType(pc, PCLU);CHKERRQ(ierr);
930552f7358SJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
931552f7358SJed Brown 
93256044e6dSMatthew G. Knepley   ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
933552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
934552f7358SJed Brown   for (p = 0; p < ctx->n; ++p) {
935a1e44745SMatthew G. Knepley     PetscScalar *x = NULL, *vertices = NULL;
936552f7358SJed Brown     PetscScalar *xi;
937cb313848SJed Brown     PetscReal    xir[3];
938552f7358SJed Brown     PetscInt     c = ctx->cells[p], comp, coordSize, xSize;
939552f7358SJed Brown 
940552f7358SJed Brown     /* Can make this do all points at once */
9410298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
9429ace16cdSJacob Faibussowitsch     PetscAssertFalse(8*3 != coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 8*3);
9430298fd71SBarry Smith     ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
9449ace16cdSJacob Faibussowitsch     PetscAssertFalse(8*ctx->dof != xSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %D", xSize, 8*ctx->dof);
9453ec1f749SStefano Zampini     ierr   = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr);
9463ec1f749SStefano Zampini     ierr   = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr);
947552f7358SJed Brown     ierr   = VecGetArray(real, &xi);CHKERRQ(ierr);
948552f7358SJed Brown     xi[0]  = coords[p*ctx->dim+0];
949552f7358SJed Brown     xi[1]  = coords[p*ctx->dim+1];
950552f7358SJed Brown     xi[2]  = coords[p*ctx->dim+2];
951552f7358SJed Brown     ierr   = VecRestoreArray(real, &xi);CHKERRQ(ierr);
952552f7358SJed Brown     ierr   = SNESSolve(snes, real, ref);CHKERRQ(ierr);
953552f7358SJed Brown     ierr   = VecGetArray(ref, &xi);CHKERRQ(ierr);
954cb313848SJed Brown     xir[0] = PetscRealPart(xi[0]);
955cb313848SJed Brown     xir[1] = PetscRealPart(xi[1]);
956cb313848SJed Brown     xir[2] = PetscRealPart(xi[2]);
957552f7358SJed Brown     for (comp = 0; comp < ctx->dof; ++comp) {
958552f7358SJed Brown       a[p*ctx->dof+comp] =
959cb313848SJed Brown         x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) +
9607a1931ceSMatthew G. Knepley         x[3*ctx->dof+comp]*    xir[0]*(1-xir[1])*(1-xir[2]) +
961cb313848SJed Brown         x[2*ctx->dof+comp]*    xir[0]*    xir[1]*(1-xir[2]) +
9627a1931ceSMatthew G. Knepley         x[1*ctx->dof+comp]*(1-xir[0])*    xir[1]*(1-xir[2]) +
963cb313848SJed Brown         x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*   xir[2] +
964cb313848SJed Brown         x[5*ctx->dof+comp]*    xir[0]*(1-xir[1])*   xir[2] +
965cb313848SJed Brown         x[6*ctx->dof+comp]*    xir[0]*    xir[1]*   xir[2] +
966cb313848SJed Brown         x[7*ctx->dof+comp]*(1-xir[0])*    xir[1]*   xir[2];
967552f7358SJed Brown     }
968552f7358SJed Brown     ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr);
9690298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr);
9700298fd71SBarry Smith     ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr);
971552f7358SJed Brown   }
972552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
97356044e6dSMatthew G. Knepley   ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
974552f7358SJed Brown 
975552f7358SJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
976552f7358SJed Brown   ierr = VecDestroy(&r);CHKERRQ(ierr);
977552f7358SJed Brown   ierr = VecDestroy(&ref);CHKERRQ(ierr);
978552f7358SJed Brown   ierr = VecDestroy(&real);CHKERRQ(ierr);
979552f7358SJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
980552f7358SJed Brown   PetscFunctionReturn(0);
981552f7358SJed Brown }
982552f7358SJed Brown 
9834267b1a3SMatthew G. Knepley /*@C
9844267b1a3SMatthew G. Knepley   DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points.
9854267b1a3SMatthew G. Knepley 
986552f7358SJed Brown   Input Parameters:
987552f7358SJed Brown + ctx - The DMInterpolationInfo context
988552f7358SJed Brown . dm  - The DM
989552f7358SJed Brown - x   - The local vector containing the field to be interpolated
990552f7358SJed Brown 
991552f7358SJed Brown   Output Parameters:
992552f7358SJed Brown . v   - The vector containing the interpolated values
9934267b1a3SMatthew G. Knepley 
9944267b1a3SMatthew G. Knepley   Note: A suitable v can be obtained using DMInterpolationGetVector().
9954267b1a3SMatthew G. Knepley 
9964267b1a3SMatthew G. Knepley   Level: beginner
9974267b1a3SMatthew G. Knepley 
9984267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationAddPoints(), DMInterpolationCreate()
9994267b1a3SMatthew G. Knepley @*/
10000adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v)
10010adebc6cSBarry Smith {
100266a0a883SMatthew G. Knepley   PetscDS        ds;
100366a0a883SMatthew G. Knepley   PetscInt       n, p, Nf, field;
100466a0a883SMatthew G. Knepley   PetscBool      useDS = PETSC_FALSE;
1005552f7358SJed Brown   PetscErrorCode ierr;
1006552f7358SJed Brown 
1007552f7358SJed Brown   PetscFunctionBegin;
1008552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1009552f7358SJed Brown   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
1010552f7358SJed Brown   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
1011552f7358SJed Brown   ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
10129ace16cdSJacob Faibussowitsch   PetscAssertFalse(n != ctx->n*ctx->dof,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %D should be %D", n, ctx->n*ctx->dof);
101366a0a883SMatthew G. Knepley   if (!n) PetscFunctionReturn(0);
1014680d18d5SMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1015680d18d5SMatthew G. Knepley   if (ds) {
101666a0a883SMatthew G. Knepley     useDS = PETSC_TRUE;
1017680d18d5SMatthew G. Knepley     ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
1018680d18d5SMatthew G. Knepley     for (field = 0; field < Nf; ++field) {
101966a0a883SMatthew G. Knepley       PetscObject  obj;
1020680d18d5SMatthew G. Knepley       PetscClassId id;
1021680d18d5SMatthew G. Knepley 
102266a0a883SMatthew G. Knepley       ierr = PetscDSGetDiscretization(ds, field, &obj);CHKERRQ(ierr);
102366a0a883SMatthew G. Knepley       ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
102466a0a883SMatthew G. Knepley       if (id != PETSCFE_CLASSID) {useDS = PETSC_FALSE; break;}
102566a0a883SMatthew G. Knepley     }
102666a0a883SMatthew G. Knepley   }
102766a0a883SMatthew G. Knepley   if (useDS) {
102866a0a883SMatthew G. Knepley     const PetscScalar *coords;
102966a0a883SMatthew G. Knepley     PetscScalar       *interpolant;
103066a0a883SMatthew G. Knepley     PetscInt           cdim, d;
103166a0a883SMatthew G. Knepley 
103266a0a883SMatthew G. Knepley     ierr = DMGetCoordinateDim(dm, &cdim);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) {
103666a0a883SMatthew G. Knepley       PetscReal    pcoords[3], xi[3];
1037680d18d5SMatthew G. Knepley       PetscScalar *xa   = NULL;
103866a0a883SMatthew G. Knepley       PetscInt     coff = 0, foff = 0, clSize;
1039680d18d5SMatthew G. Knepley 
104052aa1562SMatthew G. Knepley       if (ctx->cells[p] < 0) continue;
1041680d18d5SMatthew G. Knepley       for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p*cdim+d]);
1042680d18d5SMatthew G. Knepley       ierr = DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi);CHKERRQ(ierr);
104366a0a883SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr);
104466a0a883SMatthew G. Knepley       for (field = 0; field < Nf; ++field) {
104566a0a883SMatthew G. Knepley         PetscTabulation T;
104666a0a883SMatthew G. Knepley         PetscFE         fe;
104766a0a883SMatthew G. Knepley 
104866a0a883SMatthew G. Knepley         ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
1049680d18d5SMatthew G. Knepley         ierr = PetscFECreateTabulation(fe, 1, 1, xi, 0, &T);CHKERRQ(ierr);
1050680d18d5SMatthew G. Knepley         {
1051680d18d5SMatthew G. Knepley           const PetscReal *basis = T->T[0];
1052680d18d5SMatthew G. Knepley           const PetscInt   Nb    = T->Nb;
1053680d18d5SMatthew G. Knepley           const PetscInt   Nc    = T->Nc;
105466a0a883SMatthew G. Knepley           PetscInt         f, fc;
105566a0a883SMatthew G. Knepley 
1056680d18d5SMatthew G. Knepley           for (fc = 0; fc < Nc; ++fc) {
105766a0a883SMatthew G. Knepley             interpolant[p*ctx->dof+coff+fc] = 0.0;
1058680d18d5SMatthew G. Knepley             for (f = 0; f < Nb; ++f) {
105966a0a883SMatthew G. Knepley               interpolant[p*ctx->dof+coff+fc] += xa[foff+f]*basis[(0*Nb + f)*Nc + fc];
1060552f7358SJed Brown             }
1061680d18d5SMatthew G. Knepley           }
106266a0a883SMatthew G. Knepley           coff += Nc;
106366a0a883SMatthew G. Knepley           foff += Nb;
1064680d18d5SMatthew G. Knepley         }
1065680d18d5SMatthew G. Knepley         ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr);
1066680d18d5SMatthew G. Knepley       }
106766a0a883SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr);
10689ace16cdSJacob Faibussowitsch       PetscAssertFalse(coff != ctx->dof,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %D != %D dof specified for interpolation", coff, ctx->dof);
10699ace16cdSJacob Faibussowitsch       PetscAssertFalse(foff != clSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total FE space size %D != %D closure size", foff, clSize);
107066a0a883SMatthew G. Knepley     }
1071680d18d5SMatthew G. Knepley     ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr);
107266a0a883SMatthew G. Knepley     ierr = VecRestoreArrayWrite(v, &interpolant);CHKERRQ(ierr);
107366a0a883SMatthew G. Knepley   } else {
107466a0a883SMatthew G. Knepley     DMPolytopeType ct;
107566a0a883SMatthew G. Knepley 
1076680d18d5SMatthew G. Knepley     /* TODO Check each cell individually */
1077680d18d5SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, ctx->cells[0], &ct);CHKERRQ(ierr);
1078680d18d5SMatthew G. Knepley     switch (ct) {
1079680d18d5SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:      ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1080680d18d5SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL: ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1081680d18d5SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:   ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
1082680d18d5SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:    ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr);break;
108398921bdaSJacob Faibussowitsch       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for cell type %s", DMPolytopeTypes[ct]);
1084680d18d5SMatthew G. Knepley     }
1085552f7358SJed Brown   }
1086552f7358SJed Brown   PetscFunctionReturn(0);
1087552f7358SJed Brown }
1088552f7358SJed Brown 
10894267b1a3SMatthew G. Knepley /*@C
10904267b1a3SMatthew G. Knepley   DMInterpolationDestroy - Destroys a DMInterpolationInfo context
10914267b1a3SMatthew G. Knepley 
10924267b1a3SMatthew G. Knepley   Collective on ctx
10934267b1a3SMatthew G. Knepley 
10944267b1a3SMatthew G. Knepley   Input Parameter:
10954267b1a3SMatthew G. Knepley . ctx - the context
10964267b1a3SMatthew G. Knepley 
10974267b1a3SMatthew G. Knepley   Level: beginner
10984267b1a3SMatthew G. Knepley 
10994267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate()
11004267b1a3SMatthew G. Knepley @*/
11010adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx)
11020adebc6cSBarry Smith {
1103552f7358SJed Brown   PetscErrorCode ierr;
1104552f7358SJed Brown 
1105552f7358SJed Brown   PetscFunctionBegin;
1106064a246eSJacob Faibussowitsch   PetscValidPointer(ctx, 1);
1107552f7358SJed Brown   ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr);
1108552f7358SJed Brown   ierr = PetscFree((*ctx)->points);CHKERRQ(ierr);
1109552f7358SJed Brown   ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr);
1110552f7358SJed Brown   ierr = PetscFree(*ctx);CHKERRQ(ierr);
11110298fd71SBarry Smith   *ctx = NULL;
1112552f7358SJed Brown   PetscFunctionReturn(0);
1113552f7358SJed Brown }
1114cc0c4584SMatthew G. Knepley 
1115cc0c4584SMatthew G. Knepley /*@C
1116cc0c4584SMatthew G. Knepley   SNESMonitorFields - Monitors the residual for each field separately
1117cc0c4584SMatthew G. Knepley 
1118cc0c4584SMatthew G. Knepley   Collective on SNES
1119cc0c4584SMatthew G. Knepley 
1120cc0c4584SMatthew G. Knepley   Input Parameters:
1121cc0c4584SMatthew G. Knepley + snes   - the SNES context
1122cc0c4584SMatthew G. Knepley . its    - iteration number
1123cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual
1124d43b4f6eSBarry Smith - vf  - PetscViewerAndFormat of type ASCII
1125cc0c4584SMatthew G. Knepley 
1126cc0c4584SMatthew G. Knepley   Notes:
1127cc0c4584SMatthew G. Knepley   This routine prints the residual norm at each iteration.
1128cc0c4584SMatthew G. Knepley 
1129cc0c4584SMatthew G. Knepley   Level: intermediate
1130cc0c4584SMatthew G. Knepley 
1131cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault()
1132cc0c4584SMatthew G. Knepley @*/
1133d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
1134cc0c4584SMatthew G. Knepley {
1135d43b4f6eSBarry Smith   PetscViewer        viewer = vf->viewer;
1136cc0c4584SMatthew G. Knepley   Vec                res;
1137cc0c4584SMatthew G. Knepley   DM                 dm;
1138cc0c4584SMatthew G. Knepley   PetscSection       s;
1139cc0c4584SMatthew G. Knepley   const PetscScalar *r;
1140cc0c4584SMatthew G. Knepley   PetscReal         *lnorms, *norms;
1141cc0c4584SMatthew G. Knepley   PetscInt           numFields, f, pStart, pEnd, p;
1142cc0c4584SMatthew G. Knepley   PetscErrorCode     ierr;
1143cc0c4584SMatthew G. Knepley 
1144cc0c4584SMatthew G. Knepley   PetscFunctionBegin;
11454d4332d5SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
11469e5d0892SLisandro Dalcin   ierr = SNESGetFunction(snes, &res, NULL, NULL);CHKERRQ(ierr);
1147cc0c4584SMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
114892fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
1149cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr);
1150cc0c4584SMatthew G. Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1151cc0c4584SMatthew G. Knepley   ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr);
1152cc0c4584SMatthew G. Knepley   ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr);
1153cc0c4584SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
1154cc0c4584SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
1155cc0c4584SMatthew G. Knepley       PetscInt fdof, foff, d;
1156cc0c4584SMatthew G. Knepley 
1157cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr);
1158cc0c4584SMatthew G. Knepley       ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr);
1159cc0c4584SMatthew G. Knepley       for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d]));
1160cc0c4584SMatthew G. Knepley     }
1161cc0c4584SMatthew G. Knepley   }
1162cc0c4584SMatthew G. Knepley   ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr);
1163820f2d46SBarry Smith   ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);
1164d43b4f6eSBarry Smith   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
1165cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
1166cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr);
1167cc0c4584SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
1168cc0c4584SMatthew G. Knepley     if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
1169cc0c4584SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr);
1170cc0c4584SMatthew G. Knepley   }
1171cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr);
1172cc0c4584SMatthew G. Knepley   ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr);
1173d43b4f6eSBarry Smith   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1174cc0c4584SMatthew G. Knepley   ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr);
1175cc0c4584SMatthew G. Knepley   PetscFunctionReturn(0);
1176cc0c4584SMatthew G. Knepley }
117724cdb843SMatthew G. Knepley 
117824cdb843SMatthew G. Knepley /********************* Residual Computation **************************/
117924cdb843SMatthew G. Knepley 
11806528b96dSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
11816528b96dSMatthew G. Knepley {
11826528b96dSMatthew G. Knepley   PetscInt       depth;
11836528b96dSMatthew G. Knepley   PetscErrorCode ierr;
11846528b96dSMatthew G. Knepley 
11856528b96dSMatthew G. Knepley   PetscFunctionBegin;
11866528b96dSMatthew G. Knepley   ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
11876528b96dSMatthew G. Knepley   ierr = DMGetStratumIS(plex, "dim", depth, cellIS);CHKERRQ(ierr);
11886528b96dSMatthew G. Knepley   if (!*cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, cellIS);CHKERRQ(ierr);}
11896528b96dSMatthew G. Knepley   PetscFunctionReturn(0);
11906528b96dSMatthew G. Knepley }
11916528b96dSMatthew G. Knepley 
119224cdb843SMatthew G. Knepley /*@
11938db23a53SJed Brown   DMPlexSNESComputeResidualFEM - Sums the local residual into vector F from the local input X using pointwise functions specified by the user
119424cdb843SMatthew G. Knepley 
119524cdb843SMatthew G. Knepley   Input Parameters:
119624cdb843SMatthew G. Knepley + dm - The mesh
119724cdb843SMatthew G. Knepley . X  - Local solution
119824cdb843SMatthew G. Knepley - user - The user context
119924cdb843SMatthew G. Knepley 
120024cdb843SMatthew G. Knepley   Output Parameter:
120124cdb843SMatthew G. Knepley . F  - Local output vector
120224cdb843SMatthew G. Knepley 
12038db23a53SJed Brown   Notes:
12048db23a53SJed Brown   The residual is summed into F; the caller is responsible for using VecZeroEntries() or otherwise ensuring that any data in F is intentional.
12058db23a53SJed Brown 
120624cdb843SMatthew G. Knepley   Level: developer
120724cdb843SMatthew G. Knepley 
12087a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction()
120924cdb843SMatthew G. Knepley @*/
121024cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user)
121124cdb843SMatthew G. Knepley {
12126da023fcSToby Isaac   DM             plex;
1213083401c6SMatthew G. Knepley   IS             allcellIS;
12146528b96dSMatthew G. Knepley   PetscInt       Nds, s;
121524cdb843SMatthew G. Knepley   PetscErrorCode ierr;
121624cdb843SMatthew G. Knepley 
121724cdb843SMatthew G. Knepley   PetscFunctionBegin;
12186da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
12196528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
12206528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
12216528b96dSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
12226528b96dSMatthew G. Knepley     PetscDS          ds;
12236528b96dSMatthew G. Knepley     IS               cellIS;
122406ad1575SMatthew G. Knepley     PetscFormKey key;
12256528b96dSMatthew G. Knepley 
12266528b96dSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr);
12276528b96dSMatthew G. Knepley     key.value = 0;
12286528b96dSMatthew G. Knepley     key.field = 0;
122906ad1575SMatthew G. Knepley     key.part  = 0;
12306528b96dSMatthew G. Knepley     if (!key.label) {
12316528b96dSMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
12326528b96dSMatthew G. Knepley       cellIS = allcellIS;
12336528b96dSMatthew G. Knepley     } else {
12346528b96dSMatthew G. Knepley       IS pointIS;
12356528b96dSMatthew G. Knepley 
12366528b96dSMatthew G. Knepley       key.value = 1;
12376528b96dSMatthew G. Knepley       ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr);
12386528b96dSMatthew G. Knepley       ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
12396528b96dSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
12406528b96dSMatthew G. Knepley     }
12416528b96dSMatthew G. Knepley     ierr = DMPlexComputeResidual_Internal(plex, key, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);
12426528b96dSMatthew G. Knepley     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
12436528b96dSMatthew G. Knepley   }
12446528b96dSMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
12456528b96dSMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
12466528b96dSMatthew G. Knepley   PetscFunctionReturn(0);
12476528b96dSMatthew G. Knepley }
12486528b96dSMatthew G. Knepley 
12496528b96dSMatthew G. Knepley PetscErrorCode DMSNESComputeResidual(DM dm, Vec X, Vec F, void *user)
12506528b96dSMatthew G. Knepley {
12516528b96dSMatthew G. Knepley   DM             plex;
12526528b96dSMatthew G. Knepley   IS             allcellIS;
12536528b96dSMatthew G. Knepley   PetscInt       Nds, s;
12546528b96dSMatthew G. Knepley   PetscErrorCode ierr;
12556528b96dSMatthew G. Knepley 
12566528b96dSMatthew G. Knepley   PetscFunctionBegin;
12576528b96dSMatthew G. Knepley   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
12586528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
12596528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1260083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
1261083401c6SMatthew G. Knepley     PetscDS ds;
1262083401c6SMatthew G. Knepley     DMLabel label;
1263083401c6SMatthew G. Knepley     IS      cellIS;
1264083401c6SMatthew G. Knepley 
1265083401c6SMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr);
12666528b96dSMatthew G. Knepley     {
126706ad1575SMatthew G. Knepley       PetscWeakFormKind resmap[2] = {PETSC_WF_F0, PETSC_WF_F1};
12686528b96dSMatthew G. Knepley       PetscWeakForm     wf;
12696528b96dSMatthew G. Knepley       PetscInt          Nm = 2, m, Nk = 0, k, kp, off = 0;
127006ad1575SMatthew G. Knepley       PetscFormKey *reskeys;
12716528b96dSMatthew G. Knepley 
12726528b96dSMatthew G. Knepley       /* Get unique residual keys */
12736528b96dSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
12746528b96dSMatthew G. Knepley         PetscInt Nkm;
127506ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetSize(ds->wf->form[resmap[m]], &Nkm);CHKERRQ(ierr);
12766528b96dSMatthew G. Knepley         Nk  += Nkm;
12776528b96dSMatthew G. Knepley       }
12786528b96dSMatthew G. Knepley       ierr = PetscMalloc1(Nk, &reskeys);CHKERRQ(ierr);
12796528b96dSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
128006ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetKeys(ds->wf->form[resmap[m]], &off, reskeys);CHKERRQ(ierr);
12816528b96dSMatthew G. Knepley       }
12829ace16cdSJacob Faibussowitsch       PetscAssertFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk);
128306ad1575SMatthew G. Knepley       ierr = PetscFormKeySort(Nk, reskeys);CHKERRQ(ierr);
12846528b96dSMatthew G. Knepley       for (k = 0, kp = 1; kp < Nk; ++kp) {
12856528b96dSMatthew G. Knepley         if ((reskeys[k].label != reskeys[kp].label) || (reskeys[k].value != reskeys[kp].value)) {
12866528b96dSMatthew G. Knepley           ++k;
12876528b96dSMatthew G. Knepley           if (kp != k) reskeys[k] = reskeys[kp];
12886528b96dSMatthew G. Knepley         }
12896528b96dSMatthew G. Knepley       }
12906528b96dSMatthew G. Knepley       Nk = k;
12916528b96dSMatthew G. Knepley 
12926528b96dSMatthew G. Knepley       ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
12936528b96dSMatthew G. Knepley       for (k = 0; k < Nk; ++k) {
12946528b96dSMatthew G. Knepley         DMLabel  label = reskeys[k].label;
12956528b96dSMatthew G. Knepley         PetscInt val   = reskeys[k].value;
12966528b96dSMatthew G. Knepley 
1297083401c6SMatthew G. Knepley         if (!label) {
1298083401c6SMatthew G. Knepley           ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
1299083401c6SMatthew G. Knepley           cellIS = allcellIS;
1300083401c6SMatthew G. Knepley         } else {
1301083401c6SMatthew G. Knepley           IS pointIS;
1302083401c6SMatthew G. Knepley 
13036528b96dSMatthew G. Knepley           ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr);
1304083401c6SMatthew G. Knepley           ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
1305083401c6SMatthew G. Knepley           ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
13064a3e9fdbSToby Isaac         }
13076528b96dSMatthew G. Knepley         ierr = DMPlexComputeResidual_Internal(plex, reskeys[k], cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);
13084a3e9fdbSToby Isaac         ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
1309083401c6SMatthew G. Knepley       }
13106528b96dSMatthew G. Knepley       ierr = PetscFree(reskeys);CHKERRQ(ierr);
13116528b96dSMatthew G. Knepley     }
13126528b96dSMatthew G. Knepley   }
1313083401c6SMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
13149a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
131524cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
131624cdb843SMatthew G. Knepley }
131724cdb843SMatthew G. Knepley 
1318bdd6f66aSToby Isaac /*@
1319bdd6f66aSToby Isaac   DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X
1320bdd6f66aSToby Isaac 
1321bdd6f66aSToby Isaac   Input Parameters:
1322bdd6f66aSToby Isaac + dm - The mesh
1323bdd6f66aSToby Isaac - user - The user context
1324bdd6f66aSToby Isaac 
1325bdd6f66aSToby Isaac   Output Parameter:
1326bdd6f66aSToby Isaac . X  - Local solution
1327bdd6f66aSToby Isaac 
1328bdd6f66aSToby Isaac   Level: developer
1329bdd6f66aSToby Isaac 
13307a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction()
1331bdd6f66aSToby Isaac @*/
1332bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user)
1333bdd6f66aSToby Isaac {
1334bdd6f66aSToby Isaac   DM             plex;
1335bdd6f66aSToby Isaac   PetscErrorCode ierr;
1336bdd6f66aSToby Isaac 
1337bdd6f66aSToby Isaac   PetscFunctionBegin;
1338bdd6f66aSToby Isaac   ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr);
1339bdd6f66aSToby Isaac   ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr);
1340bdd6f66aSToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
1341bdd6f66aSToby Isaac   PetscFunctionReturn(0);
1342bdd6f66aSToby Isaac }
1343bdd6f66aSToby Isaac 
13447a73cf09SMatthew G. Knepley /*@
13458e3a2eefSMatthew G. Knepley   DMSNESComputeJacobianAction - Compute the action of the Jacobian J(X) on Y
13467a73cf09SMatthew G. Knepley 
13477a73cf09SMatthew G. Knepley   Input Parameters:
13488e3a2eefSMatthew G. Knepley + dm   - The DM
13497a73cf09SMatthew G. Knepley . X    - Local solution vector
13507a73cf09SMatthew G. Knepley . Y    - Local input vector
13517a73cf09SMatthew G. Knepley - user - The user context
13527a73cf09SMatthew G. Knepley 
13537a73cf09SMatthew G. Knepley   Output Parameter:
13548e3a2eefSMatthew G. Knepley . F    - lcoal output vector
13557a73cf09SMatthew G. Knepley 
13567a73cf09SMatthew G. Knepley   Level: developer
13577a73cf09SMatthew G. Knepley 
13588e3a2eefSMatthew G. Knepley   Notes:
13598e3a2eefSMatthew G. Knepley   Users will typically use DMSNESCreateJacobianMF() followed by MatMult() instead of calling this routine directly.
13608e3a2eefSMatthew G. Knepley 
1361a509fe9cSSatish Balay .seealso: DMSNESCreateJacobianMF(), DMPlexSNESComputeResidualFEM()
13627a73cf09SMatthew G. Knepley @*/
13638e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESComputeJacobianAction(DM dm, Vec X, Vec Y, Vec F, void *user)
1364a925c78cSMatthew G. Knepley {
13658e3a2eefSMatthew G. Knepley   DM             plex;
13668e3a2eefSMatthew G. Knepley   IS             allcellIS;
13678e3a2eefSMatthew G. Knepley   PetscInt       Nds, s;
1368a925c78cSMatthew G. Knepley   PetscErrorCode ierr;
1369a925c78cSMatthew G. Knepley 
1370a925c78cSMatthew G. Knepley   PetscFunctionBegin;
13717a73cf09SMatthew G. Knepley   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
13728e3a2eefSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
13738e3a2eefSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
13748e3a2eefSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
13758e3a2eefSMatthew G. Knepley     PetscDS ds;
13768e3a2eefSMatthew G. Knepley     DMLabel label;
13778e3a2eefSMatthew G. Knepley     IS      cellIS;
13787a73cf09SMatthew G. Knepley 
13798e3a2eefSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr);
13808e3a2eefSMatthew G. Knepley     {
138106ad1575SMatthew G. Knepley       PetscWeakFormKind jacmap[4] = {PETSC_WF_G0, PETSC_WF_G1, PETSC_WF_G2, PETSC_WF_G3};
13828e3a2eefSMatthew G. Knepley       PetscWeakForm     wf;
13838e3a2eefSMatthew G. Knepley       PetscInt          Nm = 4, m, Nk = 0, k, kp, off = 0;
138406ad1575SMatthew G. Knepley       PetscFormKey *jackeys;
13858e3a2eefSMatthew G. Knepley 
13868e3a2eefSMatthew G. Knepley       /* Get unique Jacobian keys */
13878e3a2eefSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
13888e3a2eefSMatthew G. Knepley         PetscInt Nkm;
138906ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetSize(ds->wf->form[jacmap[m]], &Nkm);CHKERRQ(ierr);
13908e3a2eefSMatthew G. Knepley         Nk  += Nkm;
13918e3a2eefSMatthew G. Knepley       }
13928e3a2eefSMatthew G. Knepley       ierr = PetscMalloc1(Nk, &jackeys);CHKERRQ(ierr);
13938e3a2eefSMatthew G. Knepley       for (m = 0; m < Nm; ++m) {
139406ad1575SMatthew G. Knepley         ierr = PetscHMapFormGetKeys(ds->wf->form[jacmap[m]], &off, jackeys);CHKERRQ(ierr);
13958e3a2eefSMatthew G. Knepley       }
13969ace16cdSJacob Faibussowitsch       PetscAssertFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk);
139706ad1575SMatthew G. Knepley       ierr = PetscFormKeySort(Nk, jackeys);CHKERRQ(ierr);
13988e3a2eefSMatthew G. Knepley       for (k = 0, kp = 1; kp < Nk; ++kp) {
13998e3a2eefSMatthew G. Knepley         if ((jackeys[k].label != jackeys[kp].label) || (jackeys[k].value != jackeys[kp].value)) {
14008e3a2eefSMatthew G. Knepley           ++k;
14018e3a2eefSMatthew G. Knepley           if (kp != k) jackeys[k] = jackeys[kp];
14028e3a2eefSMatthew G. Knepley         }
14038e3a2eefSMatthew G. Knepley       }
14048e3a2eefSMatthew G. Knepley       Nk = k;
14058e3a2eefSMatthew G. Knepley 
14068e3a2eefSMatthew G. Knepley       ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
14078e3a2eefSMatthew G. Knepley       for (k = 0; k < Nk; ++k) {
14088e3a2eefSMatthew G. Knepley         DMLabel  label = jackeys[k].label;
14098e3a2eefSMatthew G. Knepley         PetscInt val   = jackeys[k].value;
14108e3a2eefSMatthew G. Knepley 
14118e3a2eefSMatthew G. Knepley         if (!label) {
14128e3a2eefSMatthew G. Knepley           ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
14138e3a2eefSMatthew G. Knepley           cellIS = allcellIS;
14147a73cf09SMatthew G. Knepley         } else {
14158e3a2eefSMatthew G. Knepley           IS pointIS;
1416a925c78cSMatthew G. Knepley 
14178e3a2eefSMatthew G. Knepley           ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr);
14188e3a2eefSMatthew G. Knepley           ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
14198e3a2eefSMatthew G. Knepley           ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1420a925c78cSMatthew G. Knepley         }
14218e3a2eefSMatthew G. Knepley         ierr = DMPlexComputeJacobian_Action_Internal(plex, jackeys[k], cellIS, 0.0, 0.0, X, NULL, Y, F, user);CHKERRQ(ierr);
14227a73cf09SMatthew G. Knepley         ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
14238e3a2eefSMatthew G. Knepley       }
14248e3a2eefSMatthew G. Knepley       ierr = PetscFree(jackeys);CHKERRQ(ierr);
14258e3a2eefSMatthew G. Knepley     }
14268e3a2eefSMatthew G. Knepley   }
14278e3a2eefSMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
14287a73cf09SMatthew G. Knepley   ierr = DMDestroy(&plex);CHKERRQ(ierr);
1429a925c78cSMatthew G. Knepley   PetscFunctionReturn(0);
1430a925c78cSMatthew G. Knepley }
1431a925c78cSMatthew G. Knepley 
143224cdb843SMatthew G. Knepley /*@
143324cdb843SMatthew G. Knepley   DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user.
143424cdb843SMatthew G. Knepley 
143524cdb843SMatthew G. Knepley   Input Parameters:
143624cdb843SMatthew G. Knepley + dm - The mesh
143724cdb843SMatthew G. Knepley . X  - Local input vector
143824cdb843SMatthew G. Knepley - user - The user context
143924cdb843SMatthew G. Knepley 
144024cdb843SMatthew G. Knepley   Output Parameter:
144124cdb843SMatthew G. Knepley . Jac  - Jacobian matrix
144224cdb843SMatthew G. Knepley 
144324cdb843SMatthew G. Knepley   Note:
144424cdb843SMatthew G. Knepley   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
144524cdb843SMatthew G. Knepley   like a GPU, or vectorize on a multicore machine.
144624cdb843SMatthew G. Knepley 
144724cdb843SMatthew G. Knepley   Level: developer
144824cdb843SMatthew G. Knepley 
144924cdb843SMatthew G. Knepley .seealso: FormFunctionLocal()
145024cdb843SMatthew G. Knepley @*/
145124cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user)
145224cdb843SMatthew G. Knepley {
14536da023fcSToby Isaac   DM             plex;
1454083401c6SMatthew G. Knepley   IS             allcellIS;
1455f04eb4edSMatthew G. Knepley   PetscBool      hasJac, hasPrec;
14566528b96dSMatthew G. Knepley   PetscInt       Nds, s;
145724cdb843SMatthew G. Knepley   PetscErrorCode ierr;
145824cdb843SMatthew G. Knepley 
145924cdb843SMatthew G. Knepley   PetscFunctionBegin;
14606da023fcSToby Isaac   ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr);
14616528b96dSMatthew G. Knepley   ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr);
14626528b96dSMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1463083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
1464083401c6SMatthew G. Knepley     PetscDS          ds;
1465083401c6SMatthew G. Knepley     IS               cellIS;
146606ad1575SMatthew G. Knepley     PetscFormKey key;
1467083401c6SMatthew G. Knepley 
14686528b96dSMatthew G. Knepley     ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr);
14696528b96dSMatthew G. Knepley     key.value = 0;
14706528b96dSMatthew G. Knepley     key.field = 0;
147106ad1575SMatthew G. Knepley     key.part  = 0;
14726528b96dSMatthew G. Knepley     if (!key.label) {
1473083401c6SMatthew G. Knepley       ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr);
1474083401c6SMatthew G. Knepley       cellIS = allcellIS;
1475083401c6SMatthew G. Knepley     } else {
1476083401c6SMatthew G. Knepley       IS pointIS;
1477083401c6SMatthew G. Knepley 
14786528b96dSMatthew G. Knepley       key.value = 1;
14796528b96dSMatthew G. Knepley       ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr);
1480083401c6SMatthew G. Knepley       ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr);
1481083401c6SMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1482083401c6SMatthew G. Knepley     }
1483083401c6SMatthew G. Knepley     if (!s) {
1484083401c6SMatthew G. Knepley       ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr);
1485083401c6SMatthew G. Knepley       ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr);
1486f04eb4edSMatthew G. Knepley       if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);}
1487f04eb4edSMatthew G. Knepley       ierr = MatZeroEntries(JacP);CHKERRQ(ierr);
1488083401c6SMatthew G. Knepley     }
14896528b96dSMatthew G. Knepley     ierr = DMPlexComputeJacobian_Internal(plex, key, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr);
14904a3e9fdbSToby Isaac     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
1491083401c6SMatthew G. Knepley   }
1492083401c6SMatthew G. Knepley   ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
14939a81d013SToby Isaac   ierr = DMDestroy(&plex);CHKERRQ(ierr);
149424cdb843SMatthew G. Knepley   PetscFunctionReturn(0);
149524cdb843SMatthew G. Knepley }
14961878804aSMatthew G. Knepley 
14978e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx
14988e3a2eefSMatthew G. Knepley {
14998e3a2eefSMatthew G. Knepley   DM    dm;
15008e3a2eefSMatthew G. Knepley   Vec   X;
15018e3a2eefSMatthew G. Knepley   void *ctx;
15028e3a2eefSMatthew G. Knepley };
15038e3a2eefSMatthew G. Knepley 
15048e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Destroy_Private(Mat A)
15058e3a2eefSMatthew G. Knepley {
15068e3a2eefSMatthew G. Knepley   struct _DMSNESJacobianMFCtx *ctx;
15078e3a2eefSMatthew G. Knepley   PetscErrorCode               ierr;
15088e3a2eefSMatthew G. Knepley 
15098e3a2eefSMatthew G. Knepley   PetscFunctionBegin;
15103ec1f749SStefano Zampini   ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr);
15118e3a2eefSMatthew G. Knepley   ierr = MatShellSetContext(A, NULL);CHKERRQ(ierr);
15128e3a2eefSMatthew G. Knepley   ierr = DMDestroy(&ctx->dm);CHKERRQ(ierr);
15138e3a2eefSMatthew G. Knepley   ierr = VecDestroy(&ctx->X);CHKERRQ(ierr);
15148e3a2eefSMatthew G. Knepley   ierr = PetscFree(ctx);CHKERRQ(ierr);
15158e3a2eefSMatthew G. Knepley   PetscFunctionReturn(0);
15168e3a2eefSMatthew G. Knepley }
15178e3a2eefSMatthew G. Knepley 
15188e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Mult_Private(Mat A, Vec Y, Vec Z)
15198e3a2eefSMatthew G. Knepley {
15208e3a2eefSMatthew G. Knepley   struct _DMSNESJacobianMFCtx *ctx;
15218e3a2eefSMatthew G. Knepley   PetscErrorCode               ierr;
15228e3a2eefSMatthew G. Knepley 
15238e3a2eefSMatthew G. Knepley   PetscFunctionBegin;
15243ec1f749SStefano Zampini   ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr);
15258e3a2eefSMatthew G. Knepley   ierr = DMSNESComputeJacobianAction(ctx->dm, ctx->X, Y, Z, ctx->ctx);CHKERRQ(ierr);
15268e3a2eefSMatthew G. Knepley   PetscFunctionReturn(0);
15278e3a2eefSMatthew G. Knepley }
15288e3a2eefSMatthew G. Knepley 
15298e3a2eefSMatthew G. Knepley /*@
15308e3a2eefSMatthew G. Knepley   DMSNESCreateJacobianMF - Create a Mat which computes the action of the Jacobian matrix-free
15318e3a2eefSMatthew G. Knepley 
15328e3a2eefSMatthew G. Knepley   Collective on dm
15338e3a2eefSMatthew G. Knepley 
15348e3a2eefSMatthew G. Knepley   Input Parameters:
15358e3a2eefSMatthew G. Knepley + dm   - The DM
15368e3a2eefSMatthew G. Knepley . X    - The evaluation point for the Jacobian
15378e3a2eefSMatthew G. Knepley - user - A user context, or NULL
15388e3a2eefSMatthew G. Knepley 
15398e3a2eefSMatthew G. Knepley   Output Parameter:
15408e3a2eefSMatthew G. Knepley . J    - The Mat
15418e3a2eefSMatthew G. Knepley 
15428e3a2eefSMatthew G. Knepley   Level: advanced
15438e3a2eefSMatthew G. Knepley 
15448e3a2eefSMatthew G. Knepley   Notes:
15458e3a2eefSMatthew G. Knepley   Vec X is kept in Mat J, so updating X then updates the evaluation point.
15468e3a2eefSMatthew G. Knepley 
15478e3a2eefSMatthew G. Knepley .seealso: DMSNESComputeJacobianAction()
15488e3a2eefSMatthew G. Knepley @*/
15498e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESCreateJacobianMF(DM dm, Vec X, void *user, Mat *J)
15508e3a2eefSMatthew G. Knepley {
15518e3a2eefSMatthew G. Knepley   struct _DMSNESJacobianMFCtx *ctx;
15528e3a2eefSMatthew G. Knepley   PetscInt                     n, N;
15538e3a2eefSMatthew G. Knepley   PetscErrorCode               ierr;
15548e3a2eefSMatthew G. Knepley 
15558e3a2eefSMatthew G. Knepley   PetscFunctionBegin;
15568e3a2eefSMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dm), J);CHKERRQ(ierr);
15578e3a2eefSMatthew G. Knepley   ierr = MatSetType(*J, MATSHELL);CHKERRQ(ierr);
15588e3a2eefSMatthew G. Knepley   ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr);
15598e3a2eefSMatthew G. Knepley   ierr = VecGetSize(X, &N);CHKERRQ(ierr);
15608e3a2eefSMatthew G. Knepley   ierr = MatSetSizes(*J, n, n, N, N);CHKERRQ(ierr);
15618e3a2eefSMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
15628e3a2eefSMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) X);CHKERRQ(ierr);
15638e3a2eefSMatthew G. Knepley   ierr = PetscMalloc1(1, &ctx);CHKERRQ(ierr);
15648e3a2eefSMatthew G. Knepley   ctx->dm  = dm;
15658e3a2eefSMatthew G. Knepley   ctx->X   = X;
15668e3a2eefSMatthew G. Knepley   ctx->ctx = user;
15678e3a2eefSMatthew G. Knepley   ierr = MatShellSetContext(*J, ctx);CHKERRQ(ierr);
15688e3a2eefSMatthew G. Knepley   ierr = MatShellSetOperation(*J, MATOP_DESTROY, (void (*)(void)) DMSNESJacobianMF_Destroy_Private);CHKERRQ(ierr);
15698e3a2eefSMatthew G. Knepley   ierr = MatShellSetOperation(*J, MATOP_MULT,    (void (*)(void)) DMSNESJacobianMF_Mult_Private);CHKERRQ(ierr);
15708e3a2eefSMatthew G. Knepley   PetscFunctionReturn(0);
15718e3a2eefSMatthew G. Knepley }
15728e3a2eefSMatthew G. Knepley 
157338cfc46eSPierre Jolivet /*
157438cfc46eSPierre Jolivet      MatComputeNeumannOverlap - Computes an unassembled (Neumann) local overlapping Mat in nonlinear context.
157538cfc46eSPierre Jolivet 
157638cfc46eSPierre Jolivet    Input Parameters:
157738cfc46eSPierre Jolivet +     X - SNES linearization point
157838cfc46eSPierre Jolivet .     ovl - index set of overlapping subdomains
157938cfc46eSPierre Jolivet 
158038cfc46eSPierre Jolivet    Output Parameter:
158138cfc46eSPierre Jolivet .     J - unassembled (Neumann) local matrix
158238cfc46eSPierre Jolivet 
158338cfc46eSPierre Jolivet    Level: intermediate
158438cfc46eSPierre Jolivet 
158538cfc46eSPierre Jolivet .seealso: DMCreateNeumannOverlap(), MATIS, PCHPDDMSetAuxiliaryMat()
158638cfc46eSPierre Jolivet */
158738cfc46eSPierre Jolivet static PetscErrorCode MatComputeNeumannOverlap_Plex(Mat J, PetscReal t, Vec X, Vec X_t, PetscReal s, IS ovl, void *ctx)
158838cfc46eSPierre Jolivet {
158938cfc46eSPierre Jolivet   SNES           snes;
159038cfc46eSPierre Jolivet   Mat            pJ;
159138cfc46eSPierre Jolivet   DM             ovldm,origdm;
159238cfc46eSPierre Jolivet   DMSNES         sdm;
159338cfc46eSPierre Jolivet   PetscErrorCode (*bfun)(DM,Vec,void*);
159438cfc46eSPierre Jolivet   PetscErrorCode (*jfun)(DM,Vec,Mat,Mat,void*);
159538cfc46eSPierre Jolivet   void           *bctx,*jctx;
159638cfc46eSPierre Jolivet   PetscErrorCode ierr;
159738cfc46eSPierre Jolivet 
159838cfc46eSPierre Jolivet   PetscFunctionBegin;
159938cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_MATIS",(PetscObject*)&pJ);CHKERRQ(ierr);
16009ace16cdSJacob Faibussowitsch   PetscAssertFalse(!pJ,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing overlapping Mat");
160138cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Original_HPDDM",(PetscObject*)&origdm);CHKERRQ(ierr);
16029ace16cdSJacob Faibussowitsch   PetscAssertFalse(!origdm,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing original DM");
160338cfc46eSPierre Jolivet   ierr = MatGetDM(pJ,&ovldm);CHKERRQ(ierr);
160438cfc46eSPierre Jolivet   ierr = DMSNESGetBoundaryLocal(origdm,&bfun,&bctx);CHKERRQ(ierr);
160538cfc46eSPierre Jolivet   ierr = DMSNESSetBoundaryLocal(ovldm,bfun,bctx);CHKERRQ(ierr);
160638cfc46eSPierre Jolivet   ierr = DMSNESGetJacobianLocal(origdm,&jfun,&jctx);CHKERRQ(ierr);
160738cfc46eSPierre Jolivet   ierr = DMSNESSetJacobianLocal(ovldm,jfun,jctx);CHKERRQ(ierr);
160838cfc46eSPierre Jolivet   ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject*)&snes);CHKERRQ(ierr);
160938cfc46eSPierre Jolivet   if (!snes) {
161038cfc46eSPierre Jolivet     ierr = SNESCreate(PetscObjectComm((PetscObject)ovl),&snes);CHKERRQ(ierr);
161138cfc46eSPierre Jolivet     ierr = SNESSetDM(snes,ovldm);CHKERRQ(ierr);
161238cfc46eSPierre Jolivet     ierr = PetscObjectCompose((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject)snes);CHKERRQ(ierr);
161338cfc46eSPierre Jolivet     ierr = PetscObjectDereference((PetscObject)snes);CHKERRQ(ierr);
161438cfc46eSPierre Jolivet   }
161538cfc46eSPierre Jolivet   ierr = DMGetDMSNES(ovldm,&sdm);CHKERRQ(ierr);
161638cfc46eSPierre Jolivet   ierr = VecLockReadPush(X);CHKERRQ(ierr);
161738cfc46eSPierre Jolivet   PetscStackPush("SNES user Jacobian function");
161838cfc46eSPierre Jolivet   ierr = (*sdm->ops->computejacobian)(snes,X,pJ,pJ,sdm->jacobianctx);CHKERRQ(ierr);
161938cfc46eSPierre Jolivet   PetscStackPop;
162038cfc46eSPierre Jolivet   ierr = VecLockReadPop(X);CHKERRQ(ierr);
162138cfc46eSPierre Jolivet   /* this is a no-hop, just in case we decide to change the placeholder for the local Neumann matrix */
162238cfc46eSPierre Jolivet   {
162338cfc46eSPierre Jolivet     Mat locpJ;
162438cfc46eSPierre Jolivet 
162538cfc46eSPierre Jolivet     ierr = MatISGetLocalMat(pJ,&locpJ);CHKERRQ(ierr);
162638cfc46eSPierre Jolivet     ierr = MatCopy(locpJ,J,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
162738cfc46eSPierre Jolivet   }
162838cfc46eSPierre Jolivet   PetscFunctionReturn(0);
162938cfc46eSPierre Jolivet }
163038cfc46eSPierre Jolivet 
1631a925c78cSMatthew G. Knepley /*@
16329f520fc2SToby Isaac   DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian.
16339f520fc2SToby Isaac 
16349f520fc2SToby Isaac   Input Parameters:
16359f520fc2SToby Isaac + dm - The DM object
1636dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary())
16379f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual())
16389f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian())
16391a244344SSatish Balay 
16401a244344SSatish Balay   Level: developer
16419f520fc2SToby Isaac @*/
16429f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx)
16439f520fc2SToby Isaac {
16449f520fc2SToby Isaac   PetscErrorCode ierr;
16459f520fc2SToby Isaac 
16469f520fc2SToby Isaac   PetscFunctionBegin;
16479f520fc2SToby Isaac   ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr);
16489f520fc2SToby Isaac   ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr);
16499f520fc2SToby Isaac   ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr);
165038cfc46eSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",MatComputeNeumannOverlap_Plex);CHKERRQ(ierr);
16519f520fc2SToby Isaac   PetscFunctionReturn(0);
16529f520fc2SToby Isaac }
16539f520fc2SToby Isaac 
1654f017bcb6SMatthew G. Knepley /*@C
1655f017bcb6SMatthew G. Knepley   DMSNESCheckDiscretization - Check the discretization error of the exact solution
1656f017bcb6SMatthew G. Knepley 
1657f017bcb6SMatthew G. Knepley   Input Parameters:
1658f017bcb6SMatthew G. Knepley + snes - the SNES object
1659f017bcb6SMatthew G. Knepley . dm   - the DM
1660f2cacb80SMatthew G. Knepley . t    - the time
1661f017bcb6SMatthew G. Knepley . u    - a DM vector
1662f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1663f017bcb6SMatthew G. Knepley 
1664f3c94560SMatthew G. Knepley   Output Parameters:
1665f3c94560SMatthew G. Knepley . error - An array which holds the discretization error in each field, or NULL
1666f3c94560SMatthew G. Knepley 
16677f96f943SMatthew G. Knepley   Note: The user must call PetscDSSetExactSolution() beforehand
16687f96f943SMatthew G. Knepley 
1669f017bcb6SMatthew G. Knepley   Level: developer
1670f017bcb6SMatthew G. Knepley 
16717f96f943SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckResidual(), DMSNESCheckJacobian(), PetscDSSetExactSolution()
1672f017bcb6SMatthew G. Knepley @*/
1673f2cacb80SMatthew G. Knepley PetscErrorCode DMSNESCheckDiscretization(SNES snes, DM dm, PetscReal t, Vec u, PetscReal tol, PetscReal error[])
16741878804aSMatthew G. Knepley {
1675f017bcb6SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
1676f017bcb6SMatthew G. Knepley   void            **ectxs;
1677f3c94560SMatthew G. Knepley   PetscReal        *err;
16787f96f943SMatthew G. Knepley   MPI_Comm          comm;
16797f96f943SMatthew G. Knepley   PetscInt          Nf, f;
16801878804aSMatthew G. Knepley   PetscErrorCode    ierr;
16811878804aSMatthew G. Knepley 
16821878804aSMatthew G. Knepley   PetscFunctionBegin;
1683f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1684f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1685064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(u, VEC_CLASSID, 4);
1686534a8f05SLisandro Dalcin   if (error) PetscValidRealPointer(error, 6);
16877f96f943SMatthew G. Knepley 
1688f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, t, u, NULL);CHKERRQ(ierr);
16897f96f943SMatthew G. Knepley   ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr);
16907f96f943SMatthew G. Knepley 
1691f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1692f017bcb6SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
1693083401c6SMatthew G. Knepley   ierr = PetscCalloc3(Nf, &exacts, Nf, &ectxs, PetscMax(1, Nf), &err);CHKERRQ(ierr);
16947f96f943SMatthew G. Knepley   {
16957f96f943SMatthew G. Knepley     PetscInt Nds, s;
16967f96f943SMatthew G. Knepley 
1697083401c6SMatthew G. Knepley     ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
1698083401c6SMatthew G. Knepley     for (s = 0; s < Nds; ++s) {
16997f96f943SMatthew G. Knepley       PetscDS         ds;
1700083401c6SMatthew G. Knepley       DMLabel         label;
1701083401c6SMatthew G. Knepley       IS              fieldIS;
17027f96f943SMatthew G. Knepley       const PetscInt *fields;
17037f96f943SMatthew G. Knepley       PetscInt        dsNf, f;
1704083401c6SMatthew G. Knepley 
1705083401c6SMatthew G. Knepley       ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr);
1706083401c6SMatthew G. Knepley       ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr);
1707083401c6SMatthew G. Knepley       ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);
1708083401c6SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) {
1709083401c6SMatthew G. Knepley         const PetscInt field = fields[f];
1710083401c6SMatthew G. Knepley         ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr);
1711083401c6SMatthew G. Knepley       }
1712083401c6SMatthew G. Knepley       ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);
1713083401c6SMatthew G. Knepley     }
1714083401c6SMatthew G. Knepley   }
1715f017bcb6SMatthew G. Knepley   if (Nf > 1) {
1716f2cacb80SMatthew G. Knepley     ierr = DMComputeL2FieldDiff(dm, t, exacts, ectxs, u, err);CHKERRQ(ierr);
1717f017bcb6SMatthew G. Knepley     if (tol >= 0.0) {
1718f017bcb6SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
17199ace16cdSJacob Faibussowitsch         PetscAssertFalse(err[f] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g for field %D exceeds tolerance %g", (double) err[f], f, (double) tol);
17201878804aSMatthew G. Knepley       }
1721b878532fSMatthew G. Knepley     } else if (error) {
1722b878532fSMatthew G. Knepley       for (f = 0; f < Nf; ++f) error[f] = err[f];
17231878804aSMatthew G. Knepley     } else {
1724f017bcb6SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr);
1725f017bcb6SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
1726f017bcb6SMatthew G. Knepley         if (f) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);}
1727f3c94560SMatthew G. Knepley         ierr = PetscPrintf(comm, "%g", (double)err[f]);CHKERRQ(ierr);
17281878804aSMatthew G. Knepley       }
1729f017bcb6SMatthew G. Knepley       ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr);
1730f017bcb6SMatthew G. Knepley     }
1731f017bcb6SMatthew G. Knepley   } else {
1732f2cacb80SMatthew G. Knepley     ierr = DMComputeL2Diff(dm, t, exacts, ectxs, u, &err[0]);CHKERRQ(ierr);
1733f017bcb6SMatthew G. Knepley     if (tol >= 0.0) {
17349ace16cdSJacob Faibussowitsch       PetscAssertFalse(err[0] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g exceeds tolerance %g", (double) err[0], (double) tol);
1735b878532fSMatthew G. Knepley     } else if (error) {
1736b878532fSMatthew G. Knepley       error[0] = err[0];
1737f017bcb6SMatthew G. Knepley     } else {
1738f3c94560SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: %g\n", (double) err[0]);CHKERRQ(ierr);
1739f017bcb6SMatthew G. Knepley     }
1740f017bcb6SMatthew G. Knepley   }
1741f3c94560SMatthew G. Knepley   ierr = PetscFree3(exacts, ectxs, err);CHKERRQ(ierr);
1742f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1743f017bcb6SMatthew G. Knepley }
1744f017bcb6SMatthew G. Knepley 
1745f017bcb6SMatthew G. Knepley /*@C
1746f017bcb6SMatthew G. Knepley   DMSNESCheckResidual - Check the residual of the exact solution
1747f017bcb6SMatthew G. Knepley 
1748f017bcb6SMatthew G. Knepley   Input Parameters:
1749f017bcb6SMatthew G. Knepley + snes - the SNES object
1750f017bcb6SMatthew G. Knepley . dm   - the DM
1751f017bcb6SMatthew G. Knepley . u    - a DM vector
1752f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1753f017bcb6SMatthew G. Knepley 
1754f3c94560SMatthew G. Knepley   Output Parameters:
1755f3c94560SMatthew G. Knepley . residual - The residual norm of the exact solution, or NULL
1756f3c94560SMatthew G. Knepley 
1757f017bcb6SMatthew G. Knepley   Level: developer
1758f017bcb6SMatthew G. Knepley 
1759f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckJacobian()
1760f017bcb6SMatthew G. Knepley @*/
1761f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckResidual(SNES snes, DM dm, Vec u, PetscReal tol, PetscReal *residual)
1762f017bcb6SMatthew G. Knepley {
1763f017bcb6SMatthew G. Knepley   MPI_Comm       comm;
1764f017bcb6SMatthew G. Knepley   Vec            r;
1765f017bcb6SMatthew G. Knepley   PetscReal      res;
1766f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1767f017bcb6SMatthew G. Knepley 
1768f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1769f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1770f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1771f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
1772534a8f05SLisandro Dalcin   if (residual) PetscValidRealPointer(residual, 5);
1773f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1774f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr);
1775f017bcb6SMatthew G. Knepley   ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
17761878804aSMatthew G. Knepley   ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr);
17771878804aSMatthew G. Knepley   ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr);
1778f017bcb6SMatthew G. Knepley   if (tol >= 0.0) {
17799ace16cdSJacob Faibussowitsch     PetscAssertFalse(res > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Residual %g exceeds tolerance %g", (double) res, (double) tol);
1780b878532fSMatthew G. Knepley   } else if (residual) {
1781b878532fSMatthew G. Knepley     *residual = res;
1782f017bcb6SMatthew G. Knepley   } else {
1783f017bcb6SMatthew G. Knepley     ierr = PetscPrintf(comm, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr);
17841878804aSMatthew G. Knepley     ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr);
17851878804aSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr);
1786685405a1SBarry Smith     ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr);
1787685405a1SBarry Smith     ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr);
1788f017bcb6SMatthew G. Knepley   }
1789f017bcb6SMatthew G. Knepley   ierr = VecDestroy(&r);CHKERRQ(ierr);
1790f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1791f017bcb6SMatthew G. Knepley }
1792f017bcb6SMatthew G. Knepley 
1793f017bcb6SMatthew G. Knepley /*@C
1794f3c94560SMatthew G. Knepley   DMSNESCheckJacobian - Check the Jacobian of the exact solution against the residual using the Taylor Test
1795f017bcb6SMatthew G. Knepley 
1796f017bcb6SMatthew G. Knepley   Input Parameters:
1797f017bcb6SMatthew G. Knepley + snes - the SNES object
1798f017bcb6SMatthew G. Knepley . dm   - the DM
1799f017bcb6SMatthew G. Knepley . u    - a DM vector
1800f0fc11ceSJed Brown - tol  - A tolerance for the check, or -1 to print the results instead
1801f017bcb6SMatthew G. Knepley 
1802f3c94560SMatthew G. Knepley   Output Parameters:
1803f3c94560SMatthew G. Knepley + isLinear - Flag indicaing that the function looks linear, or NULL
1804f3c94560SMatthew G. Knepley - convRate - The rate of convergence of the linear model, or NULL
1805f3c94560SMatthew G. Knepley 
1806f017bcb6SMatthew G. Knepley   Level: developer
1807f017bcb6SMatthew G. Knepley 
1808f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckResidual()
1809f017bcb6SMatthew G. Knepley @*/
1810f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckJacobian(SNES snes, DM dm, Vec u, PetscReal tol, PetscBool *isLinear, PetscReal *convRate)
1811f017bcb6SMatthew G. Knepley {
1812f017bcb6SMatthew G. Knepley   MPI_Comm       comm;
1813f017bcb6SMatthew G. Knepley   PetscDS        ds;
1814f017bcb6SMatthew G. Knepley   Mat            J, M;
1815f017bcb6SMatthew G. Knepley   MatNullSpace   nullspace;
1816f3c94560SMatthew G. Knepley   PetscReal      slope, intercept;
18177f96f943SMatthew G. Knepley   PetscBool      hasJac, hasPrec, isLin = PETSC_FALSE;
1818f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1819f017bcb6SMatthew G. Knepley 
1820f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1821f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1822f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1823f3c94560SMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
1824534a8f05SLisandro Dalcin   if (isLinear) PetscValidBoolPointer(isLinear, 5);
1825064a246eSJacob Faibussowitsch   if (convRate) PetscValidRealPointer(convRate, 6);
1826f017bcb6SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr);
1827f2cacb80SMatthew G. Knepley   ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr);
1828f017bcb6SMatthew G. Knepley   /* Create and view matrices */
1829f017bcb6SMatthew G. Knepley   ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr);
18307f96f943SMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1831f017bcb6SMatthew G. Knepley   ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr);
1832f017bcb6SMatthew G. Knepley   ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr);
1833282e7bb4SMatthew G. Knepley   if (hasJac && hasPrec) {
1834282e7bb4SMatthew G. Knepley     ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr);
1835282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr);
1836f017bcb6SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) M, "Preconditioning Matrix");CHKERRQ(ierr);
1837282e7bb4SMatthew G. Knepley     ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr);
1838282e7bb4SMatthew G. Knepley     ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr);
1839282e7bb4SMatthew G. Knepley     ierr = MatDestroy(&M);CHKERRQ(ierr);
1840282e7bb4SMatthew G. Knepley   } else {
1841282e7bb4SMatthew G. Knepley     ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr);
1842282e7bb4SMatthew G. Knepley   }
1843f017bcb6SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) J, "Jacobian");CHKERRQ(ierr);
1844282e7bb4SMatthew G. Knepley   ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr);
1845282e7bb4SMatthew G. Knepley   ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr);
1846f017bcb6SMatthew G. Knepley   /* Check nullspace */
1847f017bcb6SMatthew G. Knepley   ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr);
1848f017bcb6SMatthew G. Knepley   if (nullspace) {
18491878804aSMatthew G. Knepley     PetscBool isNull;
1850f017bcb6SMatthew G. Knepley     ierr = MatNullSpaceTest(nullspace, J, &isNull);CHKERRQ(ierr);
18519ace16cdSJacob Faibussowitsch     PetscAssertFalse(!isNull,comm, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid.");
18521878804aSMatthew G. Knepley   }
1853f017bcb6SMatthew G. Knepley   /* Taylor test */
1854f017bcb6SMatthew G. Knepley   {
1855f017bcb6SMatthew G. Knepley     PetscRandom rand;
1856f017bcb6SMatthew G. Knepley     Vec         du, uhat, r, rhat, df;
1857f3c94560SMatthew G. Knepley     PetscReal   h;
1858f017bcb6SMatthew G. Knepley     PetscReal  *es, *hs, *errors;
1859f017bcb6SMatthew G. Knepley     PetscReal   hMax = 1.0, hMin = 1e-6, hMult = 0.1;
1860f017bcb6SMatthew G. Knepley     PetscInt    Nv, v;
1861f017bcb6SMatthew G. Knepley 
1862f017bcb6SMatthew G. Knepley     /* Choose a perturbation direction */
1863f017bcb6SMatthew G. Knepley     ierr = PetscRandomCreate(comm, &rand);CHKERRQ(ierr);
1864f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &du);CHKERRQ(ierr);
1865f017bcb6SMatthew G. Knepley     ierr = VecSetRandom(du, rand);CHKERRQ(ierr);
1866f017bcb6SMatthew G. Knepley     ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr);
1867f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &df);CHKERRQ(ierr);
1868f017bcb6SMatthew G. Knepley     ierr = MatMult(J, du, df);CHKERRQ(ierr);
1869f017bcb6SMatthew G. Knepley     /* Evaluate residual at u, F(u), save in vector r */
1870f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
1871f017bcb6SMatthew G. Knepley     ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr);
1872f017bcb6SMatthew G. Knepley     /* Look at the convergence of our Taylor approximation as we approach u */
1873f017bcb6SMatthew G. Knepley     for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv);
1874f017bcb6SMatthew G. Knepley     ierr = PetscCalloc3(Nv, &es, Nv, &hs, Nv, &errors);CHKERRQ(ierr);
1875f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &uhat);CHKERRQ(ierr);
1876f017bcb6SMatthew G. Knepley     ierr = VecDuplicate(u, &rhat);CHKERRQ(ierr);
1877f017bcb6SMatthew G. Knepley     for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv) {
1878f017bcb6SMatthew G. Knepley       ierr = VecWAXPY(uhat, h, du, u);CHKERRQ(ierr);
1879f017bcb6SMatthew G. Knepley       /* F(\hat u) \approx F(u) + J(u) (uhat - u) = F(u) + h * J(u) du */
1880f017bcb6SMatthew G. Knepley       ierr = SNESComputeFunction(snes, uhat, rhat);CHKERRQ(ierr);
1881f017bcb6SMatthew G. Knepley       ierr = VecAXPBYPCZ(rhat, -1.0, -h, 1.0, r, df);CHKERRQ(ierr);
1882f017bcb6SMatthew G. Knepley       ierr = VecNorm(rhat, NORM_2, &errors[Nv]);CHKERRQ(ierr);
1883f017bcb6SMatthew G. Knepley 
1884f017bcb6SMatthew G. Knepley       es[Nv] = PetscLog10Real(errors[Nv]);
1885f017bcb6SMatthew G. Knepley       hs[Nv] = PetscLog10Real(h);
1886f017bcb6SMatthew G. Knepley     }
1887f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&uhat);CHKERRQ(ierr);
1888f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&rhat);CHKERRQ(ierr);
1889f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&df);CHKERRQ(ierr);
18901878804aSMatthew G. Knepley     ierr = VecDestroy(&r);CHKERRQ(ierr);
1891f017bcb6SMatthew G. Knepley     ierr = VecDestroy(&du);CHKERRQ(ierr);
1892f017bcb6SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
1893f017bcb6SMatthew G. Knepley       if ((tol >= 0) && (errors[v] > tol)) break;
1894f017bcb6SMatthew G. Knepley       else if (errors[v] > PETSC_SMALL)    break;
1895f017bcb6SMatthew G. Knepley     }
1896f3c94560SMatthew G. Knepley     if (v == Nv) isLin = PETSC_TRUE;
1897f017bcb6SMatthew G. Knepley     ierr = PetscLinearRegression(Nv, hs, es, &slope, &intercept);CHKERRQ(ierr);
1898f017bcb6SMatthew G. Knepley     ierr = PetscFree3(es, hs, errors);CHKERRQ(ierr);
1899f017bcb6SMatthew G. Knepley     /* Slope should be about 2 */
1900f017bcb6SMatthew G. Knepley     if (tol >= 0) {
19019ace16cdSJacob Faibussowitsch       PetscAssertFalse(!isLin && PetscAbsReal(2 - slope) > tol,comm, PETSC_ERR_ARG_WRONG, "Taylor approximation convergence rate should be 2, not %0.2f", (double) slope);
1902b878532fSMatthew G. Knepley     } else if (isLinear || convRate) {
1903b878532fSMatthew G. Knepley       if (isLinear) *isLinear = isLin;
1904b878532fSMatthew G. Knepley       if (convRate) *convRate = slope;
1905f017bcb6SMatthew G. Knepley     } else {
1906f3c94560SMatthew G. Knepley       if (!isLin) {ierr = PetscPrintf(comm, "Taylor approximation converging at order %3.2f\n", (double) slope);CHKERRQ(ierr);}
1907f017bcb6SMatthew G. Knepley       else        {ierr = PetscPrintf(comm, "Function appears to be linear\n");CHKERRQ(ierr);}
1908f017bcb6SMatthew G. Knepley     }
1909f017bcb6SMatthew G. Knepley   }
19101878804aSMatthew G. Knepley   ierr = MatDestroy(&J);CHKERRQ(ierr);
19111878804aSMatthew G. Knepley   PetscFunctionReturn(0);
19121878804aSMatthew G. Knepley }
19131878804aSMatthew G. Knepley 
19147f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheck_Internal(SNES snes, DM dm, Vec u)
1915f017bcb6SMatthew G. Knepley {
1916f017bcb6SMatthew G. Knepley   PetscErrorCode ierr;
1917f017bcb6SMatthew G. Knepley 
1918f017bcb6SMatthew G. Knepley   PetscFunctionBegin;
1919f2cacb80SMatthew G. Knepley   ierr = DMSNESCheckDiscretization(snes, dm, 0.0, u, -1.0, NULL);CHKERRQ(ierr);
1920f3c94560SMatthew G. Knepley   ierr = DMSNESCheckResidual(snes, dm, u, -1.0, NULL);CHKERRQ(ierr);
1921f3c94560SMatthew G. Knepley   ierr = DMSNESCheckJacobian(snes, dm, u, -1.0, NULL, NULL);CHKERRQ(ierr);
1922f017bcb6SMatthew G. Knepley   PetscFunctionReturn(0);
1923f017bcb6SMatthew G. Knepley }
1924f017bcb6SMatthew G. Knepley 
1925bee9a294SMatthew G. Knepley /*@C
1926bee9a294SMatthew G. Knepley   DMSNESCheckFromOptions - Check the residual and Jacobian functions using the exact solution by outputting some diagnostic information
1927bee9a294SMatthew G. Knepley 
1928bee9a294SMatthew G. Knepley   Input Parameters:
1929bee9a294SMatthew G. Knepley + snes - the SNES object
19307f96f943SMatthew G. Knepley - u    - representative SNES vector
19317f96f943SMatthew G. Knepley 
19327f96f943SMatthew G. Knepley   Note: The user must call PetscDSSetExactSolution() beforehand
1933bee9a294SMatthew G. Knepley 
1934bee9a294SMatthew G. Knepley   Level: developer
1935bee9a294SMatthew G. Knepley @*/
19367f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u)
19371878804aSMatthew G. Knepley {
19381878804aSMatthew G. Knepley   DM             dm;
19391878804aSMatthew G. Knepley   Vec            sol;
19401878804aSMatthew G. Knepley   PetscBool      check;
19411878804aSMatthew G. Knepley   PetscErrorCode ierr;
19421878804aSMatthew G. Knepley 
19431878804aSMatthew G. Knepley   PetscFunctionBegin;
1944c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr);
19451878804aSMatthew G. Knepley   if (!check) PetscFunctionReturn(0);
19461878804aSMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
19471878804aSMatthew G. Knepley   ierr = VecDuplicate(u, &sol);CHKERRQ(ierr);
19481878804aSMatthew G. Knepley   ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr);
19497f96f943SMatthew G. Knepley   ierr = DMSNESCheck_Internal(snes, dm, sol);CHKERRQ(ierr);
19501878804aSMatthew G. Knepley   ierr = VecDestroy(&sol);CHKERRQ(ierr);
1951552f7358SJed Brown   PetscFunctionReturn(0);
1952552f7358SJed Brown }
1953