xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision eb9d3e4d1b0d07ce7eca2be9429d4698ffa7ae7f)
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      PetscFunctionBegin;
27      PetscCall(SNESLineSearchGetSNES(linesearch,&snes));
28      PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED));
29      PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G));
30      // determine lambda using W and G as work vecs..
31      PetscCall(VecAXPY(X,-lambda,Y));
32      PetscCall(SNESComputeFunction(snes,X,F));
33      PetscCall(SNESLineSearchComputeNorms(linesearch));
34      PetscFunctionReturn(PETSC_SUCCESS);
35   }
36 
37   PetscCall(SNESGetLineSearch(snes, &linesearch));
38   PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
39   PetscCall(SNESLineSearchShellSetApply(linesearch, shellfunc, NULL));
40 .ve
41 
42   Level: advanced
43 
44 .seealso: [](ch_snes), `SNESLineSearchShellGetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`,
45           `SNESLineSearchShellApplyFn`
46 @*/
47 PetscErrorCode SNESLineSearchShellSetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn *func, void *ctx)
48 {
49   PetscBool             flg;
50   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
51 
52   PetscFunctionBegin;
53   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
54   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
55   if (flg) {
56     shell->ctx  = ctx;
57     shell->func = func;
58   }
59   PetscFunctionReturn(PETSC_SUCCESS);
60 }
61 
62 /*@C
63   SNESLineSearchShellGetApply - Gets the apply function and context for the `SNESLINESEARCHSHELL`
64 
65   Not Collective
66 
67   Input Parameter:
68 . linesearch - the line search object
69 
70   Output Parameters:
71 + func - the user function; can be `NULL` if it is not needed, see `SNESLineSearchShellApplyFn` for calling sequence
72 - ctx  - the user function context; can be `NULL` if it is not needed
73 
74   Level: advanced
75 
76 .seealso: [](ch_snes), `SNESLineSearchShellSetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`,
77           `SNESLineSearchShellApplyFn`
78 @*/
79 PetscErrorCode SNESLineSearchShellGetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn **func, void **ctx)
80 {
81   PetscBool             flg;
82   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
83 
84   PetscFunctionBegin;
85   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
86   if (func) PetscAssertPointer(func, 2);
87   if (ctx) PetscAssertPointer(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(PETSC_SUCCESS);
94 }
95 
96 static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch)
97 {
98   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
99 
100   PetscFunctionBegin;
101   /* apply the user function */
102   if (shell->func) {
103     PetscCall((*shell->func)(linesearch, shell->ctx));
104   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetApply()");
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