xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision ccfb0f9f40a0131988d7995ed9679700dae2a75a)
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   PetscCheck(shell->func, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetApply()");
104   PetscCall((*shell->func)(linesearch, shell->ctx));
105   PetscFunctionReturn(PETSC_SUCCESS);
106 }
107 
108 static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch)
109 {
110   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
111 
112   PetscFunctionBegin;
113   PetscCall(PetscFree(shell));
114   PetscFunctionReturn(PETSC_SUCCESS);
115 }
116 
117 /*MC
118   SNESLINESEARCHSHELL - Provides an API for a user-provided line search routine.
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 `SNESLineSearchShellSetApply()`.
122 
123   Level: advanced
124 
125 .seealso: [](ch_snes), `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchShellSetApply()`,
126           `SNESLineSearchShellApplyFn`
127 M*/
128 
129 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
130 {
131   SNESLineSearch_Shell *shell;
132 
133   PetscFunctionBegin;
134   linesearch->ops->apply          = SNESLineSearchApply_Shell;
135   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
136   linesearch->ops->setfromoptions = NULL;
137   linesearch->ops->reset          = NULL;
138   linesearch->ops->view           = NULL;
139   linesearch->ops->setup          = NULL;
140 
141   PetscCall(PetscNew(&shell));
142 
143   linesearch->data = (void *)shell;
144   PetscFunctionReturn(PETSC_SUCCESS);
145 }
146