xref: /petsc/src/snes/impls/shell/snesshell.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 on SNES
12 
13    Input Parameters:
14 +  snes - the nonlinear solver context
15 -  apply - the application-provided solver routine
16 
17    Calling sequence of solve:
18 .vb
19    PetscErrorCode apply (SNES snes,Vec xout)
20 .ve
21 
22 +  snes - the preconditioner, get the application context with SNESShellGetContext()
23 -  xout - solution vector
24 
25    Notes:
26     the function MUST return an error code of 0 on success and nonzero on failure.
27 
28    Level: advanced
29 
30 .seealso: `SNESSHELL`, `SNESShellSetContext()`, `SNESShellGetContext()`
31 @*/
32 PetscErrorCode SNESShellSetSolve(SNES snes, PetscErrorCode (*solve)(SNES, Vec)) {
33   PetscFunctionBegin;
34   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35   PetscTryMethod(snes, "SNESShellSetSolve_C", (SNES, PetscErrorCode(*)(SNES, Vec)), (snes, solve));
36   PetscFunctionReturn(0);
37 }
38 
39 PetscErrorCode SNESReset_Shell(SNES snes) {
40   PetscFunctionBegin;
41   PetscFunctionReturn(0);
42 }
43 
44 PetscErrorCode SNESDestroy_Shell(SNES snes) {
45   PetscFunctionBegin;
46   PetscCall(SNESReset_Shell(snes));
47   PetscCall(PetscFree(snes->data));
48   PetscFunctionReturn(0);
49 }
50 
51 PetscErrorCode SNESSetUp_Shell(SNES snes) {
52   PetscFunctionBegin;
53   PetscFunctionReturn(0);
54 }
55 
56 PetscErrorCode SNESSetFromOptions_Shell(SNES snes, PetscOptionItems *PetscOptionsObject) {
57   PetscFunctionBegin;
58   PetscOptionsHeadBegin(PetscOptionsObject, "SNES Shell options");
59   PetscFunctionReturn(0);
60 }
61 
62 PetscErrorCode SNESView_Shell(SNES snes, PetscViewer viewer) {
63   PetscFunctionBegin;
64   PetscFunctionReturn(0);
65 }
66 
67 /*@
68     SNESShellGetContext - Returns the user-provided context associated with a shell SNES
69 
70     Not Collective
71 
72     Input Parameter:
73 .   snes - should have been created with SNESSetType(snes,SNESSHELL);
74 
75     Output Parameter:
76 .   ctx - the user provided context
77 
78     Level: advanced
79 
80     Notes:
81     This routine is intended for use within various shell routines
82 
83 .seealso: `SNESCreateShell()`, `SNESShellSetContext()`
84 @*/
85 PetscErrorCode SNESShellGetContext(SNES snes, void *ctx) {
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(0);
95 }
96 
97 /*@
98     SNESShellSetContext - sets the context for a shell SNES
99 
100    Logically Collective on SNES
101 
102     Input Parameters:
103 +   snes - the shell SNES
104 -   ctx - the context
105 
106    Level: advanced
107 
108    Fortran Notes:
109     The context can only be an integer or a PetscObject
110       unfortunately it cannot be a Fortran array or derived type.
111 
112 .seealso: `SNESCreateShell()`, `SNESShellGetContext()`
113 @*/
114 PetscErrorCode SNESShellSetContext(SNES snes, void *ctx) {
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(0);
123 }
124 
125 PetscErrorCode SNESSolve_Shell(SNES snes) {
126   SNES_Shell *shell = (SNES_Shell *)snes->data;
127 
128   PetscFunctionBegin;
129   PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first");
130   snes->reason = SNES_CONVERGED_ITS;
131   PetscCall((*shell->solve)(snes, snes->vec_sol));
132   PetscFunctionReturn(0);
133 }
134 
135 PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec)) {
136   SNES_Shell *shell = (SNES_Shell *)snes->data;
137 
138   PetscFunctionBegin;
139   shell->solve = solve;
140   PetscFunctionReturn(0);
141 }
142 
143 /*MC
144   SNESSHELL - a user provided nonlinear solver
145 
146    Level: advanced
147 
148 .seealso: `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`
149 M*/
150 
151 PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes) {
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(PetscNewLog(snes, &shell));
168   snes->data = (void *)shell;
169   PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell));
170   PetscFunctionReturn(0);
171 }
172