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