Date: 2026-06-01T23:13:38+00:00

Actual source code: snesshell.c

      1: #include <petsc/private/snesimpl.h>

      3: typedef struct {
      4:   PetscErrorCode (*solve)(SNES, Vec);
      5:   PetscCtx ctx;
      6: } SNES_Shell;

      8: /*@C
      9:   SNESShellSetSolve - Sets routine to apply as solver to a `SNESSHELL` `SNES` object

     11:   Logically Collective

     13:   Input Parameters:
     14: + snes  - the `SNES` nonlinear solver context
     15: - solve - the application-provided solver routine

     17:   Calling sequence of `apply`:
     18: + snes - the preconditioner, get the application context with `SNESShellGetContext()` provided with `SNESShellSetContext()`
     19: - xout - solution vector

     21:   Level: advanced

     23: .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESShellSetContext()`, `SNESShellGetContext()`
     24: @*/
     25: PetscErrorCode SNESShellSetSolve(SNES snes, PetscErrorCode (*solve)(SNES snes, Vec xout))
     26: {
     27:   PetscFunctionBegin;
     29:   PetscTryMethod(snes, "SNESShellSetSolve_C", (SNES, PetscErrorCode (*)(SNES, Vec)), (snes, solve));
     30:   PetscFunctionReturn(PETSC_SUCCESS);
     31: }

     33: static PetscErrorCode SNESDestroy_Shell(SNES snes)
     34: {
     35:   PetscFunctionBegin;
     36:   PetscCall(PetscFree(snes->data));
     37:   PetscFunctionReturn(PETSC_SUCCESS);
     38: }

     40: /*@
     41:   SNESShellGetContext - Returns the user-provided context associated with a `SNESSHELL`

     43:   Not Collective

     45:   Input Parameter:
     46: . snes - should have been created with `SNESSetType`(snes,`SNESSHELL`);

     48:   Output Parameter:
     49: . ctx - the user provided context

     51:   Level: advanced

     53:   Fortran Notes:
     54:   This only works when the context is a Fortran derived type or a `PetscObject`. Declare `ctx` with
     55: .vb
     56:   type(tUsertype), pointer :: ctx
     57: .ve

     59: .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellSetContext()`
     60: @*/
     61: PetscErrorCode SNESShellGetContext(SNES snes, PetscCtxRt ctx)
     62: {
     63:   PetscBool flg;

     65:   PetscFunctionBegin;
     67:   PetscAssertPointer(ctx, 2);
     68:   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
     69:   if (!flg) *(void **)ctx = NULL;
     70:   else *(void **)ctx = ((SNES_Shell *)snes->data)->ctx;
     71:   PetscFunctionReturn(PETSC_SUCCESS);
     72: }

     74: /*@
     75:   SNESShellSetContext - sets the context for a `SNESSHELL`

     77:   Logically Collective

     79:   Input Parameters:
     80: + snes - the `SNESSHELL`
     81: - ctx  - the context

     83:   Level: advanced

     85: .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellGetContext()`
     86: @*/
     87: PetscErrorCode SNESShellSetContext(SNES snes, PetscCtx ctx)
     88: {
     89:   SNES_Shell *shell = (SNES_Shell *)snes->data;
     90:   PetscBool   flg;

     92:   PetscFunctionBegin;
     94:   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
     95:   if (flg) shell->ctx = ctx;
     96:   PetscFunctionReturn(PETSC_SUCCESS);
     97: }

     99: static PetscErrorCode SNESSolve_Shell(SNES snes)
    100: {
    101:   SNES_Shell *shell = (SNES_Shell *)snes->data;

    103:   PetscFunctionBegin;
    104:   PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first");
    105:   snes->reason = SNES_CONVERGED_ITS;
    106:   PetscCall((*shell->solve)(snes, snes->vec_sol));
    107:   PetscFunctionReturn(PETSC_SUCCESS);
    108: }

    110: static PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec))
    111: {
    112:   SNES_Shell *shell = (SNES_Shell *)snes->data;

    114:   PetscFunctionBegin;
    115:   shell->solve = solve;
    116:   PetscFunctionReturn(PETSC_SUCCESS);
    117: }

    119: /*MC
    120:   SNESSHELL - a user provided nonlinear solver

    122:    Level: advanced

    124: .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESShellGetContext()`, `SNESShellSetContext()`, `SNESShellSetSolve()`
    125: M*/

    127: PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes)
    128: {
    129:   SNES_Shell *shell;

    131:   PetscFunctionBegin;
    132:   snes->ops->destroy = SNESDestroy_Shell;
    133:   snes->ops->solve   = SNESSolve_Shell;

    135:   snes->usesksp = PETSC_FALSE;
    136:   snes->usesnpc = PETSC_FALSE;

    138:   snes->alwayscomputesfinalresidual = PETSC_FALSE;

    140:   PetscCall(SNESParametersInitialize(snes));

    142:   PetscCall(PetscNew(&shell));
    143:   snes->data = (void *)shell;
    144:   PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell));
    145:   PetscFunctionReturn(PETSC_SUCCESS);
    146: }