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: $  PetscErrorCode func(SNESLinesearch, void *ctx)
 21: +  linesearch - the linesearch instance
 22: -  ctx - the above mentioned context

 24:    Usage:
 25: .vb
 26:   PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx)
 27:   {
 28:      Vec  X,Y,F,W,G;
 29:      SNES snes;
 30:      PetscFunctionBegin;
 31:      PetscCall(SNESLineSearchGetSNES(linesearch,&snes));
 32:      PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED));
 33:      PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G));
 34:      .. determine lambda using W and G as work vecs..
 35:      PetscCall(VecAXPY(X,-lambda,Y));
 36:      PetscCall(SNESComputeFunction(snes,X,F));
 37:      PetscCall(SNESLineSearchComputeNorms(linesearch));
 38:      PetscFunctionReturn(PETSC_SUCCESS);
 39:   }

 41:   ...

 43:   PetscCall(SNESGetLineSearch(snes, &linesearch));
 44:   PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
 45:   PetscCall(SNESLineSearchShellSetUserFunc(linesearch, shellfunc, NULL));
 46: .ve

 48:    Level: advanced

 50: .seealso: `SNESLineSearchShellGetUserFunc()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`
 51: @*/
 52: PetscErrorCode SNESLineSearchShellSetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc func, void *ctx)
 53: {
 54:   PetscBool             flg;
 55:   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;

 57:   PetscFunctionBegin;
 59:   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
 60:   if (flg) {
 61:     shell->ctx  = ctx;
 62:     shell->func = func;
 63:   }
 64:   PetscFunctionReturn(PETSC_SUCCESS);
 65: }

 67: /*@C
 68:    SNESLineSearchShellGetUserFunc - Gets the user function and context for the  `SNESLINESEARCHSHELL`

 70:    Not Collective

 72:    Input Parameter:
 73: .   linesearch - the line search object

 75:    Output Parameters:
 76: +    func  - the user function; can be NULL if you do not want it
 77: -    ctx   - the user function context; can be NULL if you do not want it

 79:    Level: advanced

 81: .seealso: `SNESLineSearchShellSetUserFunc()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`
 82: @*/
 83: PetscErrorCode SNESLineSearchShellGetUserFunc(SNESLineSearch linesearch, SNESLineSearchUserFunc *func, void **ctx)
 84: {
 85:   PetscBool             flg;
 86:   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;

 88:   PetscFunctionBegin;
 92:   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
 93:   if (flg) {
 94:     if (func) *func = shell->func;
 95:     if (ctx) *ctx = shell->ctx;
 96:   }
 97:   PetscFunctionReturn(PETSC_SUCCESS);
 98: }

100: static PetscErrorCode SNESLineSearchApply_Shell(SNESLineSearch linesearch)
101: {
102:   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;

104:   PetscFunctionBegin;
105:   /* apply the user function */
106:   if (shell->func) {
107:     PetscCall((*shell->func)(linesearch, shell->ctx));
108:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchShell needs to have a shell function set with SNESLineSearchShellSetUserFunc");
109:   PetscFunctionReturn(PETSC_SUCCESS);
110: }

112: static PetscErrorCode SNESLineSearchDestroy_Shell(SNESLineSearch linesearch)
113: {
114:   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;

116:   PetscFunctionBegin;
117:   PetscCall(PetscFree(shell));
118:   PetscFunctionReturn(PETSC_SUCCESS);
119: }

121: /*MC
122:    SNESLINESEARCHSHELL - Provides context for a user-provided line search routine.

124: The user routine has one argument, the SNESLineSearch context.  The user uses the interface to
125: extract line search parameters and set them accordingly when the computation is finished.

127: Any of the other line searches may serve as a guide to how this is to be done.  There is also a basic
128: template in the documentation for SNESLineSearchShellSetUserFunc().

130: Level: advanced

132: .seealso: `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`
133: M*/
134: PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
135: {
136:   SNESLineSearch_Shell *shell;

138:   PetscFunctionBegin;
139:   linesearch->ops->apply          = SNESLineSearchApply_Shell;
140:   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
141:   linesearch->ops->setfromoptions = NULL;
142:   linesearch->ops->reset          = NULL;
143:   linesearch->ops->view           = NULL;
144:   linesearch->ops->setup          = NULL;

146:   PetscCall(PetscNew(&shell));

148:   linesearch->data = (void *)shell;
149:   PetscFunctionReturn(PETSC_SUCCESS);
150: }