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