xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision 83c9f7f220f3448cfcd2a76a64462ac242b37309)
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 SNESLineSearch Shell 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 
25 $  PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx)
26 $  {
27 $     Vec  X,Y,F,W,G;
28 $     SNES snes;
29 $     PetscFunctionBegin;
30 $     PetscCall(SNESLineSearchGetSNES(linesearch,&snes));
31 $     PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED));
32 $     PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G));
33 $     .. determine lambda using W and G as work vecs..
34 $     PetscCall(VecAXPY(X,-lambda,Y));
35 $     PetscCall(SNESComputeFunction(snes,X,F));
36 $     PetscCall(SNESLineSearchComputeNorms(linesearch));
37 $     PetscFunctionReturn(0);
38 $  }
39 $
40 $  ...
41 $
42 $  PetscCall(SNESGetLineSearch(snes, &linesearch));
43 $  PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
44 $  PetscCall(SNESLineSearchShellSetUserFunc(linesearch, shellfunc, NULL));
45 
46    Level: advanced
47 
48    .seealso: `SNESLineSearchShellGetUserFunc()`, `SNESLINESEARCHSHELL`
49 @*/
50 PetscErrorCode SNESLineSearchShellSetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc func, void *ctx) {
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 shell implementation.
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()`
79 @*/
80 PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx) {
81   PetscBool             flg;
82   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
83 
84   PetscFunctionBegin;
85   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
86   if (func) PetscValidPointer(func, 2);
87   if (ctx) PetscValidPointer(ctx, 3);
88   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
89   if (flg) {
90     if (func) *func = shell->func;
91     if (ctx) *ctx = shell->ctx;
92   }
93   PetscFunctionReturn(0);
94 }
95 
96 static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch) {
97   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
98 
99   PetscFunctionBegin;
100   /* apply the user function */
101   if (shell->func) {
102     PetscCall((*shell->func)(linesearch, shell->ctx));
103   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc");
104   PetscFunctionReturn(0);
105 }
106 
107 static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch) {
108   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
109 
110   PetscFunctionBegin;
111   PetscCall(PetscFree(shell));
112   PetscFunctionReturn(0);
113 }
114 
115 /*MC
116    SNESLINESEARCHSHELL - Provides context for a user-provided line search routine.
117 
118 The user routine has one argument, the SNESLineSearch context.  The user uses the interface to
119 extract line search parameters and set them accordingly when the computation is finished.
120 
121 Any of the other line searches may serve as a guide to how this is to be done.  There is also a basic
122 template in the documentation for SNESLineSearchShellSetUserFunc().
123 
124 Level: advanced
125 
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(PetscNewLog(linesearch, &shell));
139 
140   linesearch->data = (void *)shell;
141   PetscFunctionReturn(0);
142 }
143