Date: 2025-03-29T05:58:40+00:00

Actual source code: linesearchshell.c

      1: #include <petsc/private/linesearchimpl.h>
      2: #include <petsc/private/snesimpl.h>

      4: typedef struct {
      5:   SNESLineSearchShellApplyFn *func;
      6:   void                       *ctx;
      7: } SNESLineSearch_Shell;

      9: // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
     10: /*@C
     11:   SNESLineSearchShellSetApply - Sets the apply function for the `SNESLINESEARCHSHELL` implementation.

     13:   Not Collective

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

     20:   Usage\:
     21: .vb
     22:   PetscErrorCode shellfunc(SNESLineSearch linesearch,void * ctx)
     23:   {
     24:      Vec  X,Y,F,W,G;
     25:      SNES snes;

     27:      PetscFunctionBegin;
     28:      PetscCall(SNESLineSearchGetSNES(linesearch,&snes));
     29:      PetscCall(SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_SUCCEEDED));
     30:      PetscCall(SNESLineSearchGetVecs(linesearch,&X,&F,&Y,&W,&G));
     31:      // determine lambda using W and G as work vecs..
     32:      PetscCall(VecAXPY(X,-lambda,Y));
     33:      PetscCall(SNESComputeFunction(snes,X,F));
     34:      PetscCall(SNESLineSearchComputeNorms(linesearch));
     35:      PetscFunctionReturn(PETSC_SUCCESS);
     36:   }

     38:   PetscCall(SNESGetLineSearch(snes, &linesearch));
     39:   PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
     40:   PetscCall(SNESLineSearchShellSetApply(linesearch, shellfunc, NULL));
     41: .ve

     43:   Level: advanced

     45: .seealso: [](ch_snes), `SNESLineSearchShellGetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`,
     46:           `SNESLineSearchShellApplyFn`
     47: @*/
     48: PetscErrorCode SNESLineSearchShellSetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn *func, void *ctx)
     49: {
     50:   PetscBool             flg;
     51:   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;

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

     63: /*@C
     64:   SNESLineSearchShellGetApply - Gets the apply function and context for the `SNESLINESEARCHSHELL`

     66:   Not Collective

     68:   Input Parameter:
     69: . linesearch - the line search object

     71:   Output Parameters:
     72: + func - the user function; can be `NULL` if it is not needed, see `SNESLineSearchShellApplyFn` for calling sequence
     73: - ctx  - the user function context; can be `NULL` if it is not needed

     75:   Level: advanced

     77: .seealso: [](ch_snes), `SNESLineSearchShellSetApply()`, `SNESLINESEARCHSHELL`, `SNESLineSearchType`, `SNESLineSearch`,
     78:           `SNESLineSearchShellApplyFn`
     79: @*/
     80: PetscErrorCode SNESLineSearchShellGetApply(SNESLineSearch linesearch, SNESLineSearchShellApplyFn **func, void **ctx)
     81: {
     82:   PetscBool             flg;
     83:   SNESLineSearch_Shell *shell = (SNESLineSearch_Shell *)linesearch->data;

     85:   PetscFunctionBegin;
     87:   if (func) PetscAssertPointer(func, 2);
     88:   if (ctx) PetscAssertPointer(ctx, 3);
     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 SNESLineSearchShellSetApply()");
    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 an API for a user-provided line search routine.

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

    124:   Level: advanced

    126: .seealso: [](ch_snes), `SNESLineSearch`, `SNES`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchShellSetApply()`,
    127:           `SNESLineSearchShellApplyFn`
    128: M*/

    130: PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Shell(SNESLineSearch linesearch)
    131: {
    132:   SNESLineSearch_Shell *shell;

    134:   PetscFunctionBegin;
    135:   linesearch->ops->apply          = SNESLineSearchApply_Shell;
    136:   linesearch->ops->destroy        = SNESLineSearchDestroy_Shell;
    137:   linesearch->ops->setfromoptions = NULL;
    138:   linesearch->ops->reset          = NULL;
    139:   linesearch->ops->view           = NULL;
    140:   linesearch->ops->setup          = NULL;

    142:   PetscCall(PetscNew(&shell));

    144:   linesearch->data = (void *)shell;
    145:   PetscFunctionReturn(PETSC_SUCCESS);
    146: }