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: // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
 10: /*@C
 11:   SNESLineSearchShellSetUserFunc - Sets the user function for the `SNESLINESEARCHSHELL` implementation.

 13:   Not Collective

 15:   Input Parameters:
 16: + linesearch - `SNESLineSearch` context
 17: . func       - function implementing the linesearch shell.
 18: - ctx        - context for func

 20:   Calling sequence of `func`:
 21: $  PetscErrorCode func(SNESLinesearch ls, void *ctx)
 22: + ls  - the linesearch instance
 23: - ctx - the above mentioned context

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

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

 47:   Level: advanced

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

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

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

 69:   Not Collective

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

 74:   Output Parameters:
 75: + func - the user function; can be `NULL` if it is not needed
 76: - ctx  - the user function context; can be `NULL` if it is not needed

 78:   Level: advanced

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

 87:   PetscFunctionBegin;
 89:   if (func) PetscAssertPointer(func, 2);
 90:   if (ctx) PetscAssertPointer(ctx, 3);
 91:   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, SNESLINESEARCHSHELL, &flg));
 92:   if (flg) {
 93:     if (func) *func = shell->func;
 94:     if (ctx) *ctx = shell->ctx;
 95:   }
 96:   PetscFunctionReturn(PETSC_SUCCESS);
 97: }

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

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

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

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

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

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

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

129:   Level: advanced

131: .seealso: [](ch_snes), `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`
132: 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: }