xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
1 #include <petsc/private/linesearchimpl.h>
2 #include <petsc/private/snesimpl.h>
3 
4 
5 typedef struct {
6   SNESLineSearchUserFunc func;
7   void                   *ctx;
8 } SNESLineSearch_Shell;
9 
10 /*@C
11    SNESLineSearchShellSetUserFunc - Sets the user function for the SNESLineSearch Shell 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 +  linesearch - the linesearch instance
22 -  ctx - the above mentioned context
23 
24    Usage:
25 
26 $  PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx)
27 $  {
28 $     Vec  X,Y,F,W,G;
29 $     SNES snes;
30 $     PetscFunctionBegin;
31 $     ierr = SNESLineSearchGetSNES(linesearch,&snes);CHKERRQ(ierr);
32 $     ierr = SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED);CHKERRQ(ierr);
33 $     ierr = SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G);CHKERRQ(ierr);
34 $     .. determine lambda using W and G as work vecs..
35 $     ierr = VecAXPY(X,-lambda,Y);CHKERRQ(ierr);
36 $     ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
37 $     ierr = SNESLineSearchComputeNorms(linesearch);CHKERRQ(ierr);
38 $     PetscFunctionReturn(0);
39 $  }
40 $
41 $  ...
42 $
43 $  ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
44 $  ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL);CHKERRQ(ierr);
45 $  ierr = SNESLineSearchShellSetUserFunc(linesearch, shellfunc, NULL);CHKERRQ(ierr);
46 
47    Level: advanced
48 
49    .keywords: SNESLineSearch, Shell, user, function, set
50 
51    .seealso: SNESLineSearchShellGetUserFunc(), SNESLINESEARCHSHELL
52 @*/
53 PetscErrorCode SNESLineSearchShellSetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc func, void *ctx)
54 {
55   PetscErrorCode       ierr;
56   PetscBool            flg;
57   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
58 
59   PetscFunctionBegin;
60   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
61   ierr = PetscObjectTypeCompare((PetscObject)linesearch,SNESLINESEARCHSHELL,&flg);CHKERRQ(ierr);
62   if (flg) {
63     shell->ctx  = ctx;
64     shell->func = func;
65   }
66   PetscFunctionReturn(0);
67 }
68 
69 
70 /*@C
71    SNESLineSearchShellGetUserFunc - Gets the user function and context for the shell implementation.
72 
73    Not Collective
74 
75    Input Parameter:
76 .     linesearch - the line search object
77 
78    Output Parameters:
79 +    func  - the user function; can be NULL if you do not want it
80 -    ctx   - the user function context; can be NULL if you do not want it
81 
82    Level: advanced
83 
84    .keywords: SNESLineSearch, get, Shell, user, function
85 
86    .seealso: SNESLineSearchShellSetUserFunc()
87 @*/
88 PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx)
89 {
90   PetscErrorCode       ierr;
91   PetscBool            flg;
92   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
93 
94   PetscFunctionBegin;
95   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
96   if (func) PetscValidPointer(func,2);
97   if (ctx)  PetscValidPointer(ctx,3);
98   ierr = PetscObjectTypeCompare((PetscObject)linesearch,SNESLINESEARCHSHELL,&flg);CHKERRQ(ierr);
99   if (flg) {
100     if (func) *func = shell->func;
101     if (ctx) *ctx  = shell->ctx;
102   }
103   PetscFunctionReturn(0);
104 }
105 
106 
107 static PetscErrorCode  SNESLineSearchApply_Shell(SNESLineSearch linesearch)
108 {
109   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
110   PetscErrorCode       ierr;
111 
112   PetscFunctionBegin;
113   /* apply the user function */
114   if (shell->func) {
115     ierr = (*shell->func)(linesearch, shell->ctx);CHKERRQ(ierr);
116   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc");
117   PetscFunctionReturn(0);
118 }
119 
120 static PetscErrorCode  SNESLineSearchDestroy_Shell(SNESLineSearch linesearch)
121 {
122   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
123   PetscErrorCode       ierr;
124 
125   PetscFunctionBegin;
126   ierr = PetscFree(shell);CHKERRQ(ierr);
127   PetscFunctionReturn(0);
128 }
129 
130 /*MC
131 
132 SNESLINESEARCHSHELL - Provides context for a user-provided line search routine.
133 
134 The user routine has one argument, the SNESLineSearch context.  The user uses the interface to
135 extract line search parameters and set them accordingly when the computation is finished.
136 
137 Any of the other line searches may serve as a guide to how this is to be done.  There is also a basic
138 template in the documentation for SNESLineSearchShellSetUserFunc().
139 
140 Level: advanced
141 
142 M*/
143 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
144 {
145 
146   SNESLineSearch_Shell *shell;
147   PetscErrorCode       ierr;
148 
149   PetscFunctionBegin;
150   linesearch->ops->apply          = SNESLineSearchApply_Shell;
151   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
152   linesearch->ops->setfromoptions = NULL;
153   linesearch->ops->reset          = NULL;
154   linesearch->ops->view           = NULL;
155   linesearch->ops->setup          = NULL;
156 
157   ierr = PetscNewLog(linesearch,&shell);CHKERRQ(ierr);
158 
159   linesearch->data = (void*) shell;
160   PetscFunctionReturn(0);
161 }
162