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: }