Actual source code: linesearchshell.c
1: #include <petsc/private/linesearchimpl.h>
2: #include <petsc/private/snesimpl.h>
4: typedef struct {
5: SNESLineSearchUserFunc func;
6: void *ctx;
7: } SNESLineSearch_Shell;
9: /*@C
10: SNESLineSearchShellSetUserFunc - Sets the user function for the `SNESLINESEARCHSHELL` implementation.
12: Not Collective
14: Input Parameters:
15: + linesearch - `SNESLineSearch` context
16: . func - function implementing the linesearch shell.
17: - ctx - context for func
19: Calling sequence of func:
20: + linesearch - the linesearch instance
21: - ctx - the above mentioned context
23: Usage:
24: $ PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx)
25: $ {
26: $ Vec X,Y,F,W,G;
27: $ SNES snes;
28: $ PetscFunctionBegin;
29: $ PetscCall(SNESLineSearchGetSNES(linesearch,&snes));
30: $ PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED));
31: $ PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G));
32: $ .. determine lambda using W and G as work vecs..
33: $ PetscCall(VecAXPY(X,-lambda,Y));
34: $ PetscCall(SNESComputeFunction(snes,X,F));
35: $ PetscCall(SNESLineSearchComputeNorms(linesearch));
36: $ PetscFunctionReturn(PETSC_SUCCESS);
37: $ }
38: $
39: $ ...
40: $
41: $ PetscCall(SNESGetLineSearch(snes, &linesearch));
42: $ PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
43: $ PetscCall(SNESLineSearchShellSetUserFunc(linesearch, shellfunc, NULL));
45: Level: advanced
47: .seealso: `SNESLineSearchShellGetUserFunc()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`
48: @*/
49: PetscErrorCode SNESLineSearchShellSetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc func, void *ctx)
50: {
51: PetscBool flg;
52: SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
54: PetscFunctionBegin;
56: PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
57: if (flg) {
58: shell->ctx = ctx;
59: shell->func = func;
60: }
61: PetscFunctionReturn(PETSC_SUCCESS);
62: }
64: /*@C
65: SNESLineSearchShellGetUserFunc - Gets the user function and context for the `SNESLINESEARCHSHELL`
67: Not Collective
69: Input Parameter:
70: . linesearch - the line search object
72: Output Parameters:
73: + func - the user function; can be NULL if you do not want it
74: - ctx - the user function context; can be NULL if you do not want it
76: Level: advanced
78: .seealso: `SNESLineSearchShellSetUserFunc()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`
79: @*/
80: PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx)
81: {
82: PetscBool flg;
83: SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
85: PetscFunctionBegin;
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: }
97: static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch)
98: {
99: SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
101: PetscFunctionBegin;
102: /* apply the user function */
103: if (shell->func) {
104: PetscCall((*shell->func)(linesearch, shell->ctx));
105: } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc");
106: PetscFunctionReturn(PETSC_SUCCESS);
107: }
109: static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch)
110: {
111: SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;
113: PetscFunctionBegin;
114: PetscCall(PetscFree(shell));
115: PetscFunctionReturn(PETSC_SUCCESS);
116: }
118: /*MC
119: SNESLINESEARCHSHELL - Provides context for a user-provided line search routine.
121: The user routine has one argument, the SNESLineSearch context. The user uses the interface to
122: extract line search parameters and set them accordingly when the computation is finished.
124: Any of the other line searches may serve as a guide to how this is to be done. There is also a basic
125: template in the documentation for SNESLineSearchShellSetUserFunc().
127: Level: advanced
129: .seealso: `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`
130: M*/
131: PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
132: {
133: SNESLineSearch_Shell *shell;
135: PetscFunctionBegin;
136: linesearch->ops->apply = SNESLineSearchApply_Shell;
137: linesearch->ops->destroy = SNESLineSearchDestroy_Shell;
138: linesearch->ops->setfromoptions = NULL;
139: linesearch->ops->reset = NULL;
140: linesearch->ops->view = NULL;
141: linesearch->ops->setup = NULL;
143: PetscCall(PetscNew(&shell));
145: linesearch->data = (void *)shell;
146: PetscFunctionReturn(PETSC_SUCCESS);
147: }