xref: /petsc/src/snes/impls/shell/snesshell.c (revision 34c645fd3b0199e05bec2fcc32d3597bfeb7f4f2)
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 `SNESShelletContext()`
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 SNESReset_Shell(SNES snes)
34 {
35   PetscFunctionBegin;
36   PetscFunctionReturn(PETSC_SUCCESS);
37 }
38 
39 static PetscErrorCode SNESDestroy_Shell(SNES snes)
40 {
41   PetscFunctionBegin;
42   PetscCall(SNESReset_Shell(snes));
43   PetscCall(PetscFree(snes->data));
44   PetscFunctionReturn(PETSC_SUCCESS);
45 }
46 
47 static PetscErrorCode SNESSetUp_Shell(SNES snes)
48 {
49   PetscFunctionBegin;
50   PetscFunctionReturn(PETSC_SUCCESS);
51 }
52 
53 static PetscErrorCode SNESSetFromOptions_Shell(SNES snes, PetscOptionItems *PetscOptionsObject)
54 {
55   PetscFunctionBegin;
56   PetscOptionsHeadBegin(PetscOptionsObject, "SNES Shell options");
57   PetscFunctionReturn(PETSC_SUCCESS);
58 }
59 
60 static PetscErrorCode SNESView_Shell(SNES snes, PetscViewer viewer)
61 {
62   PetscFunctionBegin;
63   PetscFunctionReturn(PETSC_SUCCESS);
64 }
65 
66 /*@
67   SNESShellGetContext - Returns the user-provided context associated with a `SNESSHELL`
68 
69   Not Collective
70 
71   Input Parameter:
72 . snes - should have been created with `SNESSetType`(snes,`SNESSHELL`);
73 
74   Output Parameter:
75 . ctx - the user provided context
76 
77   Level: advanced
78 
79 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellSetContext()`
80 @*/
81 PetscErrorCode SNESShellGetContext(SNES snes, void *ctx)
82 {
83   PetscBool flg;
84 
85   PetscFunctionBegin;
86   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
87   PetscAssertPointer(ctx, 2);
88   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
89   if (!flg) *(void **)ctx = NULL;
90   else *(void **)ctx = ((SNES_Shell *)snes->data)->ctx;
91   PetscFunctionReturn(PETSC_SUCCESS);
92 }
93 
94 /*@
95   SNESShellSetContext - sets the context for a `SNESSHELL`
96 
97   Logically Collective
98 
99   Input Parameters:
100 + snes - the `SNESSHELL`
101 - ctx  - the context
102 
103   Level: advanced
104 
105   Fortran Note:
106   The context can only be an integer or a `PetscObject` it cannot be a Fortran array or derived type.
107 
108 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellGetContext()`
109 @*/
110 PetscErrorCode SNESShellSetContext(SNES snes, void *ctx)
111 {
112   SNES_Shell *shell = (SNES_Shell *)snes->data;
113   PetscBool   flg;
114 
115   PetscFunctionBegin;
116   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
117   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
118   if (flg) shell->ctx = ctx;
119   PetscFunctionReturn(PETSC_SUCCESS);
120 }
121 
122 static PetscErrorCode SNESSolve_Shell(SNES snes)
123 {
124   SNES_Shell *shell = (SNES_Shell *)snes->data;
125 
126   PetscFunctionBegin;
127   PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first");
128   snes->reason = SNES_CONVERGED_ITS;
129   PetscCall((*shell->solve)(snes, snes->vec_sol));
130   PetscFunctionReturn(PETSC_SUCCESS);
131 }
132 
133 static PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec))
134 {
135   SNES_Shell *shell = (SNES_Shell *)snes->data;
136 
137   PetscFunctionBegin;
138   shell->solve = solve;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*MC
143   SNESSHELL - a user provided nonlinear solver
144 
145    Level: advanced
146 
147 .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESShellGetContext()`, `SNESShellSetContext()`, `SNESShellSetSolve()`
148 M*/
149 
150 PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes)
151 {
152   SNES_Shell *shell;
153 
154   PetscFunctionBegin;
155   snes->ops->destroy        = SNESDestroy_Shell;
156   snes->ops->setup          = SNESSetUp_Shell;
157   snes->ops->setfromoptions = SNESSetFromOptions_Shell;
158   snes->ops->view           = SNESView_Shell;
159   snes->ops->solve          = SNESSolve_Shell;
160   snes->ops->reset          = SNESReset_Shell;
161 
162   snes->usesksp = PETSC_FALSE;
163   snes->usesnpc = PETSC_FALSE;
164 
165   snes->alwayscomputesfinalresidual = PETSC_FALSE;
166 
167   PetscCall(PetscNew(&shell));
168   snes->data = (void *)shell;
169   PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell));
170   PetscFunctionReturn(PETSC_SUCCESS);
171 }
172