1 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/
2
3 typedef struct {
4 PetscErrorCode (*solve)(SNES, Vec);
5 PetscCtx 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 @*/
SNESShellSetSolve(SNES snes,PetscErrorCode (* solve)(SNES snes,Vec xout))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
SNESDestroy_Shell(SNES snes)33 static PetscErrorCode SNESDestroy_Shell(SNES snes)
34 {
35 PetscFunctionBegin;
36 PetscCall(PetscFree(snes->data));
37 PetscFunctionReturn(PETSC_SUCCESS);
38 }
39
40 /*@
41 SNESShellGetContext - Returns the user-provided context associated with a `SNESSHELL`
42
43 Not Collective
44
45 Input Parameter:
46 . snes - should have been created with `SNESSetType`(snes,`SNESSHELL`);
47
48 Output Parameter:
49 . ctx - the user provided context
50
51 Level: advanced
52
53 Fortran Notes:
54 This only works when the context is a Fortran derived type or a `PetscObject`. Declare `ctx` with
55 .vb
56 type(tUsertype), pointer :: ctx
57 .ve
58
59 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellSetContext()`
60 @*/
SNESShellGetContext(SNES snes,PetscCtxRt ctx)61 PetscErrorCode SNESShellGetContext(SNES snes, PetscCtxRt ctx)
62 {
63 PetscBool flg;
64
65 PetscFunctionBegin;
66 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
67 PetscAssertPointer(ctx, 2);
68 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
69 if (!flg) *(void **)ctx = NULL;
70 else *(void **)ctx = ((SNES_Shell *)snes->data)->ctx;
71 PetscFunctionReturn(PETSC_SUCCESS);
72 }
73
74 /*@
75 SNESShellSetContext - sets the context for a `SNESSHELL`
76
77 Logically Collective
78
79 Input Parameters:
80 + snes - the `SNESSHELL`
81 - ctx - the context
82
83 Level: advanced
84
85 .seealso: [](ch_snes), `SNES`, `SNESSHELL`, `SNESCreateShell()`, `SNESShellGetContext()`
86 @*/
SNESShellSetContext(SNES snes,PetscCtx ctx)87 PetscErrorCode SNESShellSetContext(SNES snes, PetscCtx ctx)
88 {
89 SNES_Shell *shell = (SNES_Shell *)snes->data;
90 PetscBool flg;
91
92 PetscFunctionBegin;
93 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
94 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESSHELL, &flg));
95 if (flg) shell->ctx = ctx;
96 PetscFunctionReturn(PETSC_SUCCESS);
97 }
98
SNESSolve_Shell(SNES snes)99 static PetscErrorCode SNESSolve_Shell(SNES snes)
100 {
101 SNES_Shell *shell = (SNES_Shell *)snes->data;
102
103 PetscFunctionBegin;
104 PetscCheck(shell->solve, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "Must call SNESShellSetSolve() first");
105 snes->reason = SNES_CONVERGED_ITS;
106 PetscCall((*shell->solve)(snes, snes->vec_sol));
107 PetscFunctionReturn(PETSC_SUCCESS);
108 }
109
SNESShellSetSolve_Shell(SNES snes,PetscErrorCode (* solve)(SNES,Vec))110 static PetscErrorCode SNESShellSetSolve_Shell(SNES snes, PetscErrorCode (*solve)(SNES, Vec))
111 {
112 SNES_Shell *shell = (SNES_Shell *)snes->data;
113
114 PetscFunctionBegin;
115 shell->solve = solve;
116 PetscFunctionReturn(PETSC_SUCCESS);
117 }
118
119 /*MC
120 SNESSHELL - a user provided nonlinear solver
121
122 Level: advanced
123
124 .seealso: [](ch_snes), `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESType`, `SNESShellGetContext()`, `SNESShellSetContext()`, `SNESShellSetSolve()`
125 M*/
126
SNESCreate_Shell(SNES snes)127 PETSC_EXTERN PetscErrorCode SNESCreate_Shell(SNES snes)
128 {
129 SNES_Shell *shell;
130
131 PetscFunctionBegin;
132 snes->ops->destroy = SNESDestroy_Shell;
133 snes->ops->solve = SNESSolve_Shell;
134
135 snes->usesksp = PETSC_FALSE;
136 snes->usesnpc = PETSC_FALSE;
137
138 snes->alwayscomputesfinalresidual = PETSC_FALSE;
139
140 PetscCall(SNESParametersInitialize(snes));
141
142 PetscCall(PetscNew(&shell));
143 snes->data = (void *)shell;
144 PetscCall(PetscObjectComposeFunction((PetscObject)snes, "SNESShellSetSolve_C", SNESShellSetSolve_Shell));
145 PetscFunctionReturn(PETSC_SUCCESS);
146 }
147