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