Actual source code: linesearchbasic.c

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

  4: static PetscErrorCode SNESLineSearchApply_Basic(SNESLineSearch linesearch)
  5: {
  6:   PetscBool changed_y, changed_w;
  7:   Vec       X, F, Y, W;
  8:   SNES      snes;
  9:   PetscReal gnorm, xnorm, ynorm, lambda;
 10:   PetscBool domainerror;

 12:   PetscFunctionBegin;
 13:   PetscCall(SNESLineSearchGetVecs(linesearch, &X, &F, &Y, &W, NULL));
 14:   PetscCall(SNESLineSearchGetNorms(linesearch, &xnorm, &gnorm, &ynorm));
 15:   PetscCall(SNESLineSearchGetLambda(linesearch, &lambda));
 16:   PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
 17:   PetscCall(SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_SUCCEEDED));

 19:   /* precheck */
 20:   PetscCall(SNESLineSearchPreCheck(linesearch, X, Y, &changed_y));

 22:   /* update */
 23:   PetscCall(VecWAXPY(W, -lambda, Y, X));
 24:   if (linesearch->ops->viproject) PetscCall((*linesearch->ops->viproject)(snes, W));

 26:   /* postcheck */
 27:   PetscCall(SNESLineSearchPostCheck(linesearch, X, Y, W, &changed_y, &changed_w));
 28:   if (changed_y) {
 29:     if (!changed_w) PetscCall(VecWAXPY(W, -lambda, Y, X));
 30:     if (linesearch->ops->viproject) PetscCall((*linesearch->ops->viproject)(snes, W));
 31:   }
 32:   if (linesearch->norms || snes->iter < snes->max_its - 1) {
 33:     PetscCall((*linesearch->ops->snesfunc)(snes, W, F));
 34:     PetscCall(SNESGetFunctionDomainError(snes, &domainerror));
 35:     if (domainerror) {
 36:       PetscCall(SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_DOMAIN));
 37:       PetscFunctionReturn(PETSC_SUCCESS);
 38:     }
 39:   }
 40:   if (linesearch->norms) {
 41:     if (!linesearch->ops->vinorm) PetscCall(VecNormBegin(F, NORM_2, &linesearch->fnorm));
 42:     PetscCall(VecNormBegin(Y, NORM_2, &linesearch->ynorm));
 43:     PetscCall(VecNormBegin(W, NORM_2, &linesearch->xnorm));
 44:     if (!linesearch->ops->vinorm) PetscCall(VecNormEnd(F, NORM_2, &linesearch->fnorm));
 45:     PetscCall(VecNormEnd(Y, NORM_2, &linesearch->ynorm));
 46:     PetscCall(VecNormEnd(W, NORM_2, &linesearch->xnorm));

 48:     if (linesearch->ops->vinorm) {
 49:       linesearch->fnorm = gnorm;

 51:       PetscCall((*linesearch->ops->vinorm)(snes, F, W, &linesearch->fnorm));
 52:     } else {
 53:       PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm));
 54:     }
 55:   }

 57:   /* copy the solution over */
 58:   PetscCall(VecCopy(W, X));
 59:   PetscFunctionReturn(PETSC_SUCCESS);
 60: }

 62: /*MC
 63:    SNESLINESEARCHBASIC - This line search implementation is not a line
 64:    search at all; it simply uses the full step.  Thus, this routine is intended
 65:    for methods with well-scaled updates; i.e. Newton's method (`SNESNEWTONLS`), on
 66:    well-behaved problems. Also named as `SNESLINESEARCHNONE`

 68:    Options Database Keys:
 69: +   -snes_linesearch_damping <damping> - search vector is scaled by this amount, default is 1.0
 70: -   -snes_linesearch_norms <flag> - whether to compute norms or not, default is true (SNESLineSearchSetComputeNorms())

 72:    Note:
 73:    For methods with ill-scaled updates (`SNESNRICHARDSON`, `SNESNCG`), a small
 74:    damping parameter may yield satisfactory but slow convergence despite
 75:    the lack of the line search.

 77:    Level: advanced

 79: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchSetDamping()`, `SNESLineSearchSetComputeNorms()`
 80: M*/
 81: PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Basic(SNESLineSearch linesearch)
 82: {
 83:   PetscFunctionBegin;
 84:   linesearch->ops->apply          = SNESLineSearchApply_Basic;
 85:   linesearch->ops->destroy        = NULL;
 86:   linesearch->ops->setfromoptions = NULL;
 87:   linesearch->ops->reset          = NULL;
 88:   linesearch->ops->view           = NULL;
 89:   linesearch->ops->setup          = NULL;
 90:   PetscFunctionReturn(PETSC_SUCCESS);
 91: }