xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision 27f49a208b01d2e827ab9db411a2d16003fe9262)
1 #include <petsc/private/linesearchimpl.h>
2 #include <petsc/private/snesimpl.h>
3 
4 typedef struct {
5   SNESLineSearchUserFunc func;
6   void                  *ctx;
7 } SNESLineSearch_Shell;
8 
9 /*@C
10    SNESLineSearchShellSetUserFunc - Sets the user function for the `SNESLINESEARCHSHELL` implementation.
11 
12    Not Collective
13 
14    Input Parameters:
15 +  linesearch - `SNESLineSearch` context
16 .  func - function implementing the linesearch shell.
17 -  ctx - context for func
18 
19    Calling sequence of `func`:
20 $  PetscErrorCode func(SNESLinesearch, void *ctx)
21 +  linesearch - the linesearch instance
22 -  ctx - the above mentioned context
23 
24    Usage:
25 .vb
26   PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx)
27   {
28      Vec  X,Y,F,W,G;
29      SNES snes;
30      PetscFunctionBegin;
31      PetscCall(SNESLineSearchGetSNES(linesearch,&snes));
32      PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED));
33      PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G));
34      .. determine lambda using W and G as work vecs..
35      PetscCall(VecAXPY(X,-lambda,Y));
36      PetscCall(SNESComputeFunction(snes,X,F));
37      PetscCall(SNESLineSearchComputeNorms(linesearch));
38      PetscFunctionReturn(PETSC_SUCCESS);
39   }
40 
41   ...
42 
43   PetscCall(SNESGetLineSearch(snes, &linesearch));
44   PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
45   PetscCall(SNESLineSearchShellSetUserFunc(linesearch, shellfunc, NULL));
46 .ve
47 
48    Level: advanced
49 
50 .seealso: `SNESLineSearchShellGetUserFunc()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`
51 @*/
52 PetscErrorCode SNESLineSearchShellSetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc func, void *ctx)
53 {
54   PetscBool             flg;
55   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
56 
57   PetscFunctionBegin;
58   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
59   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
60   if (flg) {
61     shell->ctx  = ctx;
62     shell->func = func;
63   }
64   PetscFunctionReturn(PETSC_SUCCESS);
65 }
66 
67 /*@C
68    SNESLineSearchShellGetUserFunc - Gets the user function and context for the  `SNESLINESEARCHSHELL`
69 
70    Not Collective
71 
72    Input Parameter:
73 .   linesearch - the line search object
74 
75    Output Parameters:
76 +    func  - the user function; can be NULL if you do not want it
77 -    ctx   - the user function context; can be NULL if you do not want it
78 
79    Level: advanced
80 
81 .seealso: `SNESLineSearchShellSetUserFunc()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`
82 @*/
83 PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx)
84 {
85   PetscBool             flg;
86   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
87 
88   PetscFunctionBegin;
89   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
90   if (func) PetscValidPointer(func, 2);
91   if (ctx) PetscValidPointer(ctx, 3);
92   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
93   if (flg) {
94     if (func) *func = shell->func;
95     if (ctx) *ctx = shell->ctx;
96   }
97   PetscFunctionReturn(PETSC_SUCCESS);
98 }
99 
100 static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch)
101 {
102   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
103 
104   PetscFunctionBegin;
105   /* apply the user function */
106   if (shell->func) {
107     PetscCall((*shell->func)(linesearch, shell->ctx));
108   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc");
109   PetscFunctionReturn(PETSC_SUCCESS);
110 }
111 
112 static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch)
113 {
114   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
115 
116   PetscFunctionBegin;
117   PetscCall(PetscFree(shell));
118   PetscFunctionReturn(PETSC_SUCCESS);
119 }
120 
121 /*MC
122    SNESLINESEARCHSHELL - Provides context for a user-provided line search routine.
123 
124 The user routine has one argument, the SNESLineSearch context.  The user uses the interface to
125 extract line search parameters and set them accordingly when the computation is finished.
126 
127 Any of the other line searches may serve as a guide to how this is to be done.  There is also a basic
128 template in the documentation for SNESLineSearchShellSetUserFunc().
129 
130 Level: advanced
131 
132 .seealso: `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`
133 M*/
134 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
135 {
136   SNESLineSearch_Shell *shell;
137 
138   PetscFunctionBegin;
139   linesearch->ops->apply          = SNESLineSearchApply_Shell;
140   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
141   linesearch->ops->setfromoptions = NULL;
142   linesearch->ops->reset          = NULL;
143   linesearch->ops->view           = NULL;
144   linesearch->ops->setup          = NULL;
145 
146   PetscCall(PetscNew(&shell));
147 
148   linesearch->data = (void *)shell;
149   PetscFunctionReturn(PETSC_SUCCESS);
150 }
151