xref: /petsc/src/snes/impls/shell/snesshell.c (revision 5544a5bc068ab743e489f2e333f3664c6a477a2a)
1 #include <petsc/private/snesimpl.h> /*I   "petscsnes.h"   I*/
2 
3 typedef struct {
4   PetscErrorCode (*solve)(SNES, Vec);
5   void *ctx;
6 } SNES_Shell;
7 
8 /*@C
9   SNESShellSetSolve - Sets routine to apply as solver to a `SNESSHELL` `SNES` object
10 
11   Logically Collective
12 
13   Input Parameters:
14 + snes  - the `SNES` nonlinear solver context
15 - solve - the application-provided solver routine
16 
17   Calling sequence of `apply`:
18 + snes - the preconditioner, get the application context with `SNESShellGetContext()` provided with `SNESShellSetContext()`
19 - xout - solution vector
20 
21   Level: advanced
22 
23 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESShellSetContext()`, `SNESShellGetContext()`
24 @*/
25 PetscErrorCode SNESShellSetSolve(SNES snes, PetscErrorCode (*solve)(SNES snes, Vec xout))
26 {
27   PetscFunctionBegin;
28   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29   PetscTryMethod(snes, "SNESShellSetSolve_C", (SNES, PetscErrorCode (*)(SNES, Vec)), (snes, solve));
30   PetscFunctionReturn(PETSC_SUCCESS);
31 }
32 
33 static PetscErrorCode SNESDestroy_Shell(SNES snes)
34 {
35   PetscFunctionBegin;
36   PetscCall(PetscFree(snes->data));
37   PetscFunctionReturn(PETSC_SUCCESS);
38 }
39 
40 static PetscErrorCode SNESSetFromOptions_Shell(SNES snes, PetscOptionItems *PetscOptionsObject)
41 {
42   PetscFunctionBegin;
43   PetscOptionsHeadBegin(PetscOptionsObject, "SNES Shell options");
44   PetscFunctionReturn(PETSC_SUCCESS);
45 }
46 
47 /*@
48   SNESShellGetContext - Returns the user-provided context associated with a `SNESSHELL`
49 
50   Not Collective
51 
52   Input Parameter:
53 . snes - should have been created with `SNESSetType`(snes,`SNESSHELL`);
54 
55   Output Parameter:
56 . ctx - the user provided context
57 
58   Level: advanced
59 
60 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellSetContext()`
61 @*/
62 PetscErrorCode SNESShellGetContext(SNES snes, void *ctx)
63 {
64   PetscBool flg;
65 
66   PetscFunctionBegin;
67   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
68   PetscAssertPointer(ctx, 2);
69   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
70   if (!flg) *(void **)ctx = NULL;
71   else *(void **)ctx = ((SNES_Shell *)snes->data)->ctx;
72   PetscFunctionReturn(PETSC_SUCCESS);
73 }
74 
75 /*@
76   SNESShellSetContext - sets the context for a `SNESSHELL`
77 
78   Logically Collective
79 
80   Input Parameters:
81 + snes - the `SNESSHELL`
82 - ctx  - the context
83 
84   Level: advanced
85 
86   Fortran Note:
87   The context can only be an integer or a `PetscObject` it cannot be a Fortran array or derived type.
88 
89 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellGetContext()`
90 @*/
91 PetscErrorCode SNESShellSetContext(SNES snes, void *ctx)
92 {
93   SNES_Shell *shell = (SNES_Shell *)snes->data;
94   PetscBool   flg;
95 
96   PetscFunctionBegin;
97   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
98   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
99   if (flg) shell->ctx = ctx;
100   PetscFunctionReturn(PETSC_SUCCESS);
101 }
102 
103 static PetscErrorCode SNESSolve_Shell(SNES snes)
104 {
105   SNES_Shell *shell = (SNES_Shell *)snes->data;
106 
107   PetscFunctionBegin;
108   PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first");
109   snes->reason = SNES_CONVERGED_ITS;
110   PetscCall((*shell->solve)(snes, snes->vec_sol));
111   PetscFunctionReturn(PETSC_SUCCESS);
112 }
113 
114 static PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec))
115 {
116   SNES_Shell *shell = (SNES_Shell *)snes->data;
117 
118   PetscFunctionBegin;
119   shell->solve = solve;
120   PetscFunctionReturn(PETSC_SUCCESS);
121 }
122 
123 /*MC
124   SNESSHELL - a user provided nonlinear solver
125 
126    Level: advanced
127 
128 .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESShellGetContext()`, `SNESShellSetContext()`, `SNESShellSetSolve()`
129 M*/
130 
131 PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes)
132 {
133   SNES_Shell *shell;
134 
135   PetscFunctionBegin;
136   snes->ops->destroy        = SNESDestroy_Shell;
137   snes->ops->setfromoptions = SNESSetFromOptions_Shell;
138   snes->ops->solve          = SNESSolve_Shell;
139 
140   snes->usesksp = PETSC_FALSE;
141   snes->usesnpc = PETSC_FALSE;
142 
143   snes->alwayscomputesfinalresidual = PETSC_FALSE;
144 
145   PetscCall(SNESParametersInitialize(snes));
146 
147   PetscCall(PetscNew(&shell));
148   snes->data = (void *)shell;
149   PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell));
150   PetscFunctionReturn(PETSC_SUCCESS);
151 }
152