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