xref: /petsc/src/snes/linesearch/impls/shell/linesearchshell.c (revision d49bb8f946631d5470c2a737c5ecfe1ed81df0b7)
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    .keywords: SNESLineSearch, Shell, user, function, set
49 
50    .seealso: SNESLineSearchShellGetUserFunc(), SNESLINESEARCHSHELL
51 @*/
52 PetscErrorCode SNESLineSearchShellSetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc func, void *ctx)
53 {
54   PetscErrorCode       ierr;
55   PetscBool            flg;
56   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
57 
58   PetscFunctionBegin;
59   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
60   ierr = PetscObjectTypeCompare((PetscObject)linesearch,SNESLINESEARCHSHELL,&flg);CHKERRQ(ierr);
61   if (flg) {
62     shell->ctx  = ctx;
63     shell->func = func;
64   }
65   PetscFunctionReturn(0);
66 }
67 
68 /*@C
69    SNESLineSearchShellGetUserFunc - Gets the user function and context for the shell implementation.
70 
71    Not Collective
72 
73    Input Parameter:
74 .     linesearch - the line search object
75 
76    Output Parameters:
77 +    func  - the user function; can be NULL if you do not want it
78 -    ctx   - the user function context; can be NULL if you do not want it
79 
80    Level: advanced
81 
82    .keywords: SNESLineSearch, get, Shell, user, function
83 
84    .seealso: SNESLineSearchShellSetUserFunc()
85 @*/
86 PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx)
87 {
88   PetscErrorCode       ierr;
89   PetscBool            flg;
90   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
91 
92   PetscFunctionBegin;
93   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
94   if (func) PetscValidPointer(func,2);
95   if (ctx)  PetscValidPointer(ctx,3);
96   ierr = PetscObjectTypeCompare((PetscObject)linesearch,SNESLINESEARCHSHELL,&flg);CHKERRQ(ierr);
97   if (flg) {
98     if (func) *func = shell->func;
99     if (ctx) *ctx  = shell->ctx;
100   }
101   PetscFunctionReturn(0);
102 }
103 
104 static PetscErrorCode  SNESLineSearchApply_Shell(SNESLineSearch linesearch)
105 {
106   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
107   PetscErrorCode       ierr;
108 
109   PetscFunctionBegin;
110   /* apply the user function */
111   if (shell->func) {
112     ierr = (*shell->func)(linesearch, shell->ctx);CHKERRQ(ierr);
113   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc");
114   PetscFunctionReturn(0);
115 }
116 
117 static PetscErrorCode  SNESLineSearchDestroy_Shell(SNESLineSearch linesearch)
118 {
119   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell*)linesearch->data;
120   PetscErrorCode       ierr;
121 
122   PetscFunctionBegin;
123   ierr = PetscFree(shell);CHKERRQ(ierr);
124   PetscFunctionReturn(0);
125 }
126 
127 /*MC
128    SNESLINESEARCHSHELL - Provides context for a user-provided line search routine.
129 
130 The user routine has one argument, the SNESLineSearch context.  The user uses the interface to
131 extract line search parameters and set them accordingly when the computation is finished.
132 
133 Any of the other line searches may serve as a guide to how this is to be done.  There is also a basic
134 template in the documentation for SNESLineSearchShellSetUserFunc().
135 
136 Level: advanced
137 
138 M*/
139 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
140 {
141 
142   SNESLineSearch_Shell *shell;
143   PetscErrorCode       ierr;
144 
145   PetscFunctionBegin;
146   linesearch->ops->apply          = SNESLineSearchApply_Shell;
147   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
148   linesearch->ops->setfromoptions = NULL;
149   linesearch->ops->reset          = NULL;
150   linesearch->ops->view           = NULL;
151   linesearch->ops->setup          = NULL;
152 
153   ierr = PetscNewLog(linesearch,&shell);CHKERRQ(ierr);
154 
155   linesearch->data = (void*) shell;
156   PetscFunctionReturn(0);
157 }
158