#include /*I "petscsnes.h" I*/ #include /*I "petscdm.h" I*/ static PetscErrorCode DMSNESUnsetFunctionContext_DMSNES(DMSNES sdm) { PetscFunctionBegin; PetscCall(PetscObjectCompose((PetscObject)sdm, "function ctx", NULL)); sdm->functionctxcontainer = NULL; PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode DMSNESUnsetJacobianContext_DMSNES(DMSNES sdm) { PetscFunctionBegin; PetscCall(PetscObjectCompose((PetscObject)sdm, "jacobian ctx", NULL)); sdm->jacobianctxcontainer = NULL; PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode DMSNESDestroy(DMSNES *kdm) { PetscFunctionBegin; if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS); PetscValidHeaderSpecific((*kdm), DMSNES_CLASSID, 1); if (--((PetscObject)(*kdm))->refct > 0) { *kdm = NULL; PetscFunctionReturn(PETSC_SUCCESS); } PetscCall(DMSNESUnsetFunctionContext_DMSNES(*kdm)); PetscCall(DMSNESUnsetJacobianContext_DMSNES(*kdm)); if ((*kdm)->ops->destroy) PetscCall(((*kdm)->ops->destroy)(*kdm)); PetscCall(PetscHeaderDestroy(kdm)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode DMSNESLoad(DMSNES kdm, PetscViewer viewer) { PetscFunctionBegin; PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->computefunction, 1, NULL, PETSC_FUNCTION)); PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->computejacobian, 1, NULL, PETSC_FUNCTION)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode DMSNESView(DMSNES kdm, PetscViewer viewer) { PetscBool isascii, isbinary; PetscFunctionBegin; PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); if (isascii) { #if defined(PETSC_SERIALIZE_FUNCTIONS) const char *fname; PetscCall(PetscFPTFind(kdm->ops->computefunction, &fname)); if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, "Function used by SNES: %s\n", fname)); PetscCall(PetscFPTFind(kdm->ops->computejacobian, &fname)); if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, "Jacobian function used by SNES: %s\n", fname)); #endif } else if (isbinary) { struct { PetscErrorCode (*func)(SNES, Vec, Vec, void *); } funcstruct; struct { PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *); } jacstruct; funcstruct.func = kdm->ops->computefunction; jacstruct.jac = kdm->ops->computejacobian; PetscCall(PetscViewerBinaryWrite(viewer, &funcstruct, 1, PETSC_FUNCTION)); PetscCall(PetscViewerBinaryWrite(viewer, &jacstruct, 1, PETSC_FUNCTION)); } PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode DMSNESCreate(MPI_Comm comm, DMSNES *kdm) { PetscFunctionBegin; PetscCall(SNESInitializePackage()); PetscCall(PetscHeaderCreate(*kdm, DMSNES_CLASSID, "DMSNES", "DMSNES", "DMSNES", comm, DMSNESDestroy, DMSNESView)); PetscFunctionReturn(PETSC_SUCCESS); } /* Attaches the DMSNES to the coarse level. * Under what conditions should we copy versus duplicate? */ static PetscErrorCode DMCoarsenHook_DMSNES(DM dm, DM dmc, void *ctx) { PetscFunctionBegin; PetscCall(DMCopyDMSNES(dm, dmc)); PetscFunctionReturn(PETSC_SUCCESS); } /* This could restrict auxiliary information to the coarse level. */ static PetscErrorCode DMRestrictHook_DMSNES(DM dm, Mat Restrict, Vec rscale, Mat Inject, DM dmc, void *ctx) { PetscFunctionBegin; PetscFunctionReturn(PETSC_SUCCESS); } /* Attaches the DMSNES to the subdomain. */ static PetscErrorCode DMSubDomainHook_DMSNES(DM dm, DM subdm, void *ctx) { PetscFunctionBegin; PetscCall(DMCopyDMSNES(dm, subdm)); PetscFunctionReturn(PETSC_SUCCESS); } /* This could restrict auxiliary information to the coarse level. */ static PetscErrorCode DMSubDomainRestrictHook_DMSNES(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) { PetscFunctionBegin; PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode DMRefineHook_DMSNES(DM dm, DM dmf, void *ctx) { PetscFunctionBegin; PetscCall(DMCopyDMSNES(dm, dmf)); PetscFunctionReturn(PETSC_SUCCESS); } /* This could restrict auxiliary information to the coarse level. */ static PetscErrorCode DMInterpolateHook_DMSNES(DM dm, Mat Interp, DM dmf, void *ctx) { PetscFunctionBegin; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESCopy - copies the information in a `DMSNES` to another `DMSNES` Not Collective Input Parameters: + kdm - Original `DMSNES` - nkdm - `DMSNES` to receive the data, should have been created with `DMSNESCreate()` Level: developer .seealso: `DMSNES`, `DMSNESCreate()`, `DMSNESDestroy()` @*/ PetscErrorCode DMSNESCopy(DMSNES kdm, DMSNES nkdm) { PetscFunctionBegin; PetscValidHeaderSpecific(kdm, DMSNES_CLASSID, 1); PetscValidHeaderSpecific(nkdm, DMSNES_CLASSID, 2); nkdm->ops->computefunction = kdm->ops->computefunction; nkdm->ops->computejacobian = kdm->ops->computejacobian; nkdm->ops->computegs = kdm->ops->computegs; nkdm->ops->computeobjective = kdm->ops->computeobjective; nkdm->ops->computepjacobian = kdm->ops->computepjacobian; nkdm->ops->computepfunction = kdm->ops->computepfunction; nkdm->ops->destroy = kdm->ops->destroy; nkdm->ops->duplicate = kdm->ops->duplicate; nkdm->gsctx = kdm->gsctx; nkdm->pctx = kdm->pctx; nkdm->objectivectx = kdm->objectivectx; nkdm->originaldm = kdm->originaldm; nkdm->functionctxcontainer = kdm->functionctxcontainer; nkdm->jacobianctxcontainer = kdm->jacobianctxcontainer; if (nkdm->functionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "function ctx", (PetscObject)nkdm->functionctxcontainer)); if (nkdm->jacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "jacobian ctx", (PetscObject)nkdm->jacobianctxcontainer)); /* nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0]; nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1]; nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2]; */ /* implementation specific copy hooks */ PetscTryTypeMethod(kdm, duplicate, nkdm); PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMGetDMSNES - get read-only private `DMSNES` context from a `DM` Not Collective Input Parameter: . dm - `DM` to be used with `SNES` Output Parameter: . snesdm - private `DMSNES` context Level: developer Note: Use `DMGetDMSNESWrite()` if write access is needed. The DMSNESSetXXX API should be used wherever possible. .seealso: `DMGetDMSNESWrite()` @*/ PetscErrorCode DMGetDMSNES(DM dm, DMSNES *snesdm) { PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); *snesdm = (DMSNES)dm->dmsnes; if (!*snesdm) { PetscCall(PetscInfo(dm, "Creating new DMSNES\n")); PetscCall(DMSNESCreate(PetscObjectComm((PetscObject)dm), snesdm)); dm->dmsnes = (PetscObject)*snesdm; (*snesdm)->originaldm = dm; PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMSNES, DMRestrictHook_DMSNES, NULL)); PetscCall(DMRefineHookAdd(dm, DMRefineHook_DMSNES, DMInterpolateHook_DMSNES, NULL)); PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_DMSNES, DMSubDomainRestrictHook_DMSNES, NULL)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMGetDMSNESWrite - get write access to private `DMSNES` context from a `DM` Not Collective Input Parameter: . dm - `DM` to be used with `SNES` Output Parameter: . snesdm - private `DMSNES` context Level: developer .seealso: `DMGetDMSNES()` @*/ PetscErrorCode DMGetDMSNESWrite(DM dm, DMSNES *snesdm) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNES(dm, &sdm)); PetscCheck(sdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMSNES has a NULL originaldm"); if (sdm->originaldm != dm) { /* Copy on write */ DMSNES oldsdm = sdm; PetscCall(PetscInfo(dm, "Copying DMSNES due to write\n")); PetscCall(DMSNESCreate(PetscObjectComm((PetscObject)dm), &sdm)); PetscCall(DMSNESCopy(oldsdm, sdm)); PetscCall(DMSNESDestroy((DMSNES *)&dm->dmsnes)); dm->dmsnes = (PetscObject)sdm; sdm->originaldm = dm; } *snesdm = sdm; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMCopyDMSNES - copies a `DMSNES` context to a new `DM` Logically Collective Input Parameters: + dmsrc - `DM` to obtain context from - dmdest - `DM` to add context to Level: developer Note: The context is copied by reference. This function does not ensure that a context exists. .seealso: `DMGetDMSNES()`, `SNESSetDM()` @*/ PetscErrorCode DMCopyDMSNES(DM dmsrc, DM dmdest) { PetscFunctionBegin; PetscValidHeaderSpecific(dmsrc, DM_CLASSID, 1); PetscValidHeaderSpecific(dmdest, DM_CLASSID, 2); if (!dmdest->dmsnes) PetscCall(DMSNESCreate(PetscObjectComm((PetscObject)dmdest), (DMSNES *)&dmdest->dmsnes)); PetscCall(DMSNESCopy((DMSNES)dmsrc->dmsnes, (DMSNES)dmdest->dmsnes)); PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMSNES, NULL, NULL)); PetscCall(DMRefineHookAdd(dmdest, DMRefineHook_DMSNES, NULL, NULL)); PetscCall(DMSubDomainHookAdd(dmdest, DMSubDomainHook_DMSNES, DMSubDomainRestrictHook_DMSNES, NULL)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetFunction - set `SNES` residual evaluation function Not Collective Input Parameters: + dm - DM to be used with `SNES` . f - residual evaluation function; see `SNESFunction` for details - ctx - context for residual evaluation Level: advanced Note: `SNESSetFunction()` is normally used, but it calls this function internally because the user context is actually associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or not. Developer Note: If `DM` took a more central role at some later date, this could become the primary method of setting the residual. .seealso: `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `SNESFunction` @*/ PetscErrorCode DMSNESSetFunction(DM dm, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNESWrite(dm, &sdm)); if (f) sdm->ops->computefunction = f; if (ctx) { PetscContainer ctxcontainer; PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)sdm), &ctxcontainer)); PetscCall(PetscContainerSetPointer(ctxcontainer, ctx)); PetscCall(PetscObjectCompose((PetscObject)sdm, "function ctx", (PetscObject)ctxcontainer)); sdm->functionctxcontainer = ctxcontainer; PetscCall(PetscContainerDestroy(&ctxcontainer)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetFunctionContextDestroy - set `SNES` residual evaluation context destroy function Not Collective Input Parameters: + dm - `DM` to be used with `SNES` - f - residual evaluation context destroy function Level: advanced .seealso: `DMSNESSetFunction()`, `SNESSetFunction()` @*/ PetscErrorCode DMSNESSetFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *)) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNESWrite(dm, &sdm)); if (sdm->functionctxcontainer) PetscCall(PetscContainerSetUserDestroy(sdm->functionctxcontainer, f)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode DMSNESUnsetFunctionContext_Internal(DM dm) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNESWrite(dm, &sdm)); PetscCall(DMSNESUnsetFunctionContext_DMSNES(sdm)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetMFFunction - set `SNES` residual evaluation function used in applying the matrix-free Jacobian with -snes_mf_operator Logically Collective Input Parameters: + dm - `DM` to be used with `SNES` - f - residual evaluation function; see `SNESFunction` for details Level: advanced .seealso: `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `SNESFunction`, `DMSNESSetFunction()` @*/ PetscErrorCode DMSNESSetMFFunction(DM dm, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); if (f || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm)); if (f) sdm->ops->computemffunction = f; if (ctx) sdm->mffunctionctx = ctx; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESGetFunction - get `SNES` residual evaluation function Not Collective Input Parameter: . dm - `DM` to be used with `SNES` Output Parameters: + f - residual evaluation function; see `SNESFunction` for details - ctx - context for residual evaluation Level: advanced Note: `SNESGetFunction()` is normally used, but it calls this function internally because the user context is actually associated with the `DM`. .seealso: `DMSNESSetContext()`, `DMSNESSetFunction()`, `SNESSetFunction()`, `SNESFunction` @*/ PetscErrorCode DMSNESGetFunction(DM dm, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNES(dm, &sdm)); if (f) *f = sdm->ops->computefunction; if (ctx) { if (sdm->functionctxcontainer) PetscCall(PetscContainerGetPointer(sdm->functionctxcontainer, ctx)); else *ctx = NULL; } PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetObjective - set `SNES` objective evaluation function Not Collective Input Parameters: + dm - `DM` to be used with `SNES` . obj - objective evaluation function; see `SNESObjectiveFunction` for details - ctx - context for residual evaluation Level: advanced .seealso: `DMSNESSetContext()`, `SNESGetObjective()`, `DMSNESSetFunction()` @*/ PetscErrorCode DMSNESSetObjective(DM dm, PetscErrorCode (*obj)(SNES, Vec, PetscReal *, void *), void *ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); if (obj || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm)); if (obj) sdm->ops->computeobjective = obj; if (ctx) sdm->objectivectx = ctx; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESGetObjective - get `SNES` objective evaluation function Not Collective Input Parameter: . dm - `DM` to be used with `SNES` Output Parameters: + obj- residual evaluation function; see `SNESObjectiveFunction` for details - ctx - context for residual evaluation Level: advanced Note: `SNESGetFunction()` is normally used, but it calls this function internally because the user context is actually associated with the `DM`. .seealso: `DMSNESSetContext()`, `DMSNESSetObjective()`, `SNESSetFunction()` @*/ PetscErrorCode DMSNESGetObjective(DM dm, PetscErrorCode (**obj)(SNES, Vec, PetscReal *, void *), void **ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNES(dm, &sdm)); if (obj) *obj = sdm->ops->computeobjective; if (ctx) *ctx = sdm->objectivectx; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetNGS - set `SNES` Gauss-Seidel relaxation function Not Collective Input Parameters: + dm - `DM` to be used with `SNES` . f - relaxation function, see `SNESGSFunction` - ctx - context for residual evaluation Level: advanced Note: `SNESSetNGS()` is normally used, but it calls this function internally because the user context is actually associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or not. Dveloper Note: If `DM` took a more central role at some later date, this could become the primary method of supplying the smoother .seealso: `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `DMSNESSetFunction()`, `SNESGSFunction` @*/ PetscErrorCode DMSNESSetNGS(DM dm, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); if (f || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm)); if (f) sdm->ops->computegs = f; if (ctx) sdm->gsctx = ctx; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESGetNGS - get `SNES` Gauss-Seidel relaxation function Not Collective Input Parameter: . dm - `DM` to be used with `SNES` Output Parameters: + f - relaxation function which performs Gauss-Seidel sweeps, see `SNESSetNGS()` - ctx - context for residual evaluation Level: advanced Note: `SNESGetNGS()` is normally used, but it calls this function internally because the user context is actually associated with the `DM`. Developer Note: This makes the interface consistent regardless of whether the user interacts with a `DM` or not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual. .seealso: `DMSNESSetContext()`, `SNESGetNGS()`, `DMSNESGetJacobian()`, `DMSNESGetFunction()` @*/ PetscErrorCode DMSNESGetNGS(DM dm, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNES(dm, &sdm)); if (f) *f = sdm->ops->computegs; if (ctx) *ctx = sdm->gsctx; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetJacobian - set `SNES` Jacobian evaluation function Not Collective Input Parameters: + dm - `DM` to be used with `SNES` . J - Jacobian evaluation function - ctx - context for residual evaluation Level: advanced Note: `SNESSetJacobian()` is normally used, but it calls this function internally because the user context is actually associated with the `DM`. Developer Note: This makes the interface consistent regardless of whether the user interacts with a `DM` or not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian. .seealso: `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESGetJacobian()`, `SNESSetJacobian()`, `SNESJacobianFunction` @*/ PetscErrorCode DMSNESSetJacobian(DM dm, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); if (J || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm)); if (J) sdm->ops->computejacobian = J; if (ctx) { PetscContainer ctxcontainer; PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)sdm), &ctxcontainer)); PetscCall(PetscContainerSetPointer(ctxcontainer, ctx)); PetscCall(PetscObjectCompose((PetscObject)sdm, "jacobian ctx", (PetscObject)ctxcontainer)); sdm->jacobianctxcontainer = ctxcontainer; PetscCall(PetscContainerDestroy(&ctxcontainer)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetJacobianContextDestroy - set `SNES` Jacobian evaluation context destroy function Not Collective Input Parameters: + dm - `DM` to be used with `SNES` - f - Jacobian evaluation context destroy function Level: advanced .seealso: `DMSNESSetJacobian()` @*/ PetscErrorCode DMSNESSetJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *)) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNESWrite(dm, &sdm)); if (sdm->jacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(sdm->jacobianctxcontainer, f)); PetscFunctionReturn(PETSC_SUCCESS); } PetscErrorCode DMSNESUnsetJacobianContext_Internal(DM dm) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNESWrite(dm, &sdm)); PetscCall(DMSNESUnsetJacobianContext_DMSNES(sdm)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESGetJacobian - get `SNES` Jacobian evaluation function Not Collective Input Parameter: . dm - `DM` to be used with `SNES` Output Parameters: + J - Jacobian evaluation function; for all calling sequence see `SNESJacobianFunction` - ctx - context for residual evaluation Level: advanced Note: `SNESGetJacobian()` is normally used, but it calls this function internally because the user context is actually associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or not. Developer Note: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian. .seealso: `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `SNESJacobianFunction` @*/ PetscErrorCode DMSNESGetJacobian(DM dm, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNES(dm, &sdm)); if (J) *J = sdm->ops->computejacobian; if (ctx) { if (sdm->jacobianctxcontainer) PetscCall(PetscContainerGetPointer(sdm->jacobianctxcontainer, ctx)); else *ctx = NULL; } PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions. Not Collective Input Parameters: + dm - `DM` to be used with `SNES` . b - RHS evaluation function . J - Picard matrix evaluation function - ctx - context for residual evaluation Level: advanced .seealso: `SNESSetPicard()`, `DMSNESSetFunction()`, `DMSNESSetJacobian()` @*/ PetscErrorCode DMSNESSetPicard(DM dm, PetscErrorCode (*b)(SNES, Vec, Vec, void *), PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNES(dm, &sdm)); if (b) sdm->ops->computepfunction = b; if (J) sdm->ops->computepjacobian = J; if (ctx) sdm->pctx = ctx; PetscFunctionReturn(PETSC_SUCCESS); } /*@C DMSNESGetPicard - get `SNES` Picard iteration evaluation functions Not Collective Input Parameter: . dm - `DM` to be used with `SNES` Output Parameters: + b - RHS evaluation function; see `SNESFunction` for details . J - RHS evaluation function; see `SNESJacobianFunction` for detailsa - ctx - context for residual evaluation Level: advanced .seealso: `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()` @*/ PetscErrorCode DMSNESGetPicard(DM dm, PetscErrorCode (**b)(SNES, Vec, Vec, void *), PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx) { DMSNES sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscCall(DMGetDMSNES(dm, &sdm)); if (b) *b = sdm->ops->computepfunction; if (J) *J = sdm->ops->computepjacobian; if (ctx) *ctx = sdm->pctx; PetscFunctionReturn(PETSC_SUCCESS); }