xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision b9c875b8ccb0466cfbdbcc08c79b487b3a7d395f)
1 #include <petsc/private/linesearchimpl.h>
2 #include <petsc/private/snesimpl.h>
3 
4 typedef struct {
5   SNESLineSearchShellApplyFn *func;
6   void                       *ctx;
7 } SNESLineSearch_Shell;
8 
9 // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
10 /*@C
11   SNESLineSearchShellSetApply - Sets the apply function for the `SNESLINESEARCHSHELL` implementation.
12 
13   Not Collective
14 
15   Input Parameters:
16 + linesearch - `SNESLineSearch` context
17 . func       - function implementing the linesearch shell, see `SNESLineSearchShellApplyFn` for calling sequence
18 - ctx        - context for func
19 
20   Usage\:
21 .vb
22   PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx)
23   {
24      Vec  X,Y,F,W,G;
25      SNES snes;
26 
27      PetscFunctionBegin;
28      PetscCall(SNESLineSearchGetSNES(linesearch,&snes));
29      PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED));
30      PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G));
31      // determine lambda using W and G as work vecs..
32      PetscCall(VecAXPY(X,-lambda,Y));
33      PetscCall(SNESComputeFunction(snes,X,F));
34      PetscCall(SNESLineSearchComputeNorms(linesearch));
35      PetscFunctionReturn(PETSC_SUCCESS);
36   }
37 
38   PetscCall(SNESGetLineSearch(snes, &linesearch));
39   PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
40   PetscCall(SNESLineSearchShellSetApply(linesearch, shellfunc, NULL));
41 .ve
42 
43   Level: advanced
44 
45 .seealso: [](ch_snes), `SNESLineSearchShellGetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`,
46           `SNESLineSearchShellApplyFn`
47 @*/
48 PetscErrorCode SNESLineSearchShellSetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn *func, void *ctx)
49 {
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(PETSC_SUCCESS);
61 }
62 
63 /*@C
64   SNESLineSearchShellGetApply - Gets the apply 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 it is not needed, see `SNESLineSearchShellApplyFn` for calling sequence
73 - ctx  - the user function context; can be `NULL` if it is not needed
74 
75   Level: advanced
76 
77 .seealso: [](ch_snes), `SNESLineSearchShellSetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`,
78           `SNESLineSearchShellApplyFn`
79 @*/
80 PetscErrorCode SNESLineSearchShellGetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn **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) PetscAssertPointer(func, 2);
88   if (ctx) PetscAssertPointer(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(PETSC_SUCCESS);
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 SNESLineSearchShellSetApply()");
106   PetscFunctionReturn(PETSC_SUCCESS);
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(PETSC_SUCCESS);
116 }
117 
118 /*MC
119   SNESLINESEARCHSHELL - Provides an API for a user-provided line search routine.
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 `SNESLineSearchShellSetApply()`.
123 
124   Level: advanced
125 
126 .seealso: [](ch_snes), `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchShellSetApply()`,
127           `SNESLineSearchShellApplyFn`
128 M*/
129 
130 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
131 {
132   SNESLineSearch_Shell *shell;
133 
134   PetscFunctionBegin;
135   linesearch->ops->apply          = SNESLineSearchApply_Shell;
136   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
137   linesearch->ops->setfromoptions = NULL;
138   linesearch->ops->reset          = NULL;
139   linesearch->ops->view           = NULL;
140   linesearch->ops->setup          = NULL;
141 
142   PetscCall(PetscNew(&shell));
143 
144   linesearch->data = (void *)shell;
145   PetscFunctionReturn(PETSC_SUCCESS);
146 }
147