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