xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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 {
51   PetscBool             flg;
52   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
53 
54   PetscFunctionBegin;
55   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
56   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
57   if (flg) {
58     shell->ctx  = ctx;
59     shell->func = func;
60   }
61   PetscFunctionReturn(0);
62 }
63 
64 /*@C
65    SNESLineSearchShellGetUserFunc - Gets the user function and context for the  `SNESLINESEARCHSHELL`
66 
67    Not Collective
68 
69    Input Parameter:
70 .   linesearch - the line search object
71 
72    Output Parameters:
73 +    func  - the user function; can be NULL if you do not want it
74 -    ctx   - the user function context; can be NULL if you do not want it
75 
76    Level: advanced
77 
78 .seealso: `SNESLineSearchShellSetUserFunc()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`
79 @*/
80 PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx)
81 {
82   PetscBool             flg;
83   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
84 
85   PetscFunctionBegin;
86   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
87   if (func) PetscValidPointer(func, 2);
88   if (ctx) PetscValidPointer(ctx, 3);
89   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
90   if (flg) {
91     if (func) *func = shell->func;
92     if (ctx) *ctx = shell->ctx;
93   }
94   PetscFunctionReturn(0);
95 }
96 
97 static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch)
98 {
99   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
100 
101   PetscFunctionBegin;
102   /* apply the user function */
103   if (shell->func) {
104     PetscCall((*shell->func)(linesearch, shell->ctx));
105   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc");
106   PetscFunctionReturn(0);
107 }
108 
109 static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch)
110 {
111   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
112 
113   PetscFunctionBegin;
114   PetscCall(PetscFree(shell));
115   PetscFunctionReturn(0);
116 }
117 
118 /*MC
119    SNESLINESEARCHSHELL - Provides context for a user-provided line search routine.
120 
121 The user routine has one argument, the SNESLineSearch context.  The user uses the interface to
122 extract line search parameters and set them accordingly when the computation is finished.
123 
124 Any of the other line searches may serve as a guide to how this is to be done.  There is also a basic
125 template in the documentation for SNESLineSearchShellSetUserFunc().
126 
127 Level: advanced
128 
129 .seealso: `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`
130 M*/
131 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
132 {
133   SNESLineSearch_Shell *shell;
134 
135   PetscFunctionBegin;
136   linesearch->ops->apply          = SNESLineSearchApply_Shell;
137   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
138   linesearch->ops->setfromoptions = NULL;
139   linesearch->ops->reset          = NULL;
140   linesearch->ops->view           = NULL;
141   linesearch->ops->setup          = NULL;
142 
143   PetscCall(PetscNew(&shell));
144 
145   linesearch->data = (void *)shell;
146   PetscFunctionReturn(0);
147 }
148