Actual source code: linesearchnone.c
1: #include <petsc/private/linesearchimpl.h>
2: #include <petsc/private/snesimpl.h>
4: static PetscErrorCode SNESLineSearchApply_None(SNESLineSearch linesearch)
5: {
6: PetscBool changed_y, changed_w;
7: Vec X, F, Y, W;
8: SNES snes;
9: PetscReal gnorm, xnorm, ynorm, lambda, fnorm = 0.0;
11: PetscFunctionBegin;
12: PetscCall(SNESLineSearchGetVecs(linesearch, &X, &F, &Y, &W, NULL));
13: PetscCall(SNESLineSearchGetNorms(linesearch, &xnorm, &gnorm, &ynorm));
14: /* SNESLineSearchSetUp() sets linesearch->lambda to linesearch->damping */
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(VecNorm(F, NORM_2, &fnorm));
35: SNESLineSearchCheckFunctionDomainError(snes, linesearch, fnorm);
36: }
37: if (linesearch->norms) {
38: PetscCall(VecNormBegin(Y, NORM_2, &linesearch->ynorm));
39: PetscCall(VecNormBegin(W, NORM_2, &linesearch->xnorm));
40: PetscCall(VecNormEnd(Y, NORM_2, &linesearch->ynorm));
41: PetscCall(VecNormEnd(W, NORM_2, &linesearch->xnorm));
43: if (linesearch->ops->vinorm) {
44: linesearch->fnorm = gnorm;
46: PetscCall((*linesearch->ops->vinorm)(snes, F, W, &linesearch->fnorm));
47: } else linesearch->fnorm = fnorm;
48: }
50: /* copy the solution over */
51: PetscCall(VecCopy(W, X));
52: PetscFunctionReturn(PETSC_SUCCESS);
53: }
55: static PetscErrorCode SNESLineSearchView_None(SNESLineSearch linesearch, PetscViewer viewer)
56: {
57: PetscBool isascii;
59: PetscFunctionBegin;
60: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
61: if (isascii && linesearch->damping != 1.) PetscCall(PetscViewerASCIIPrintf(viewer, " damping factor: %g\n", (double)linesearch->damping));
62: PetscFunctionReturn(PETSC_SUCCESS);
63: }
65: /*MC
66: SNESLINESEARCHNONE - This line search implementation is not a line
67: search at all; it simply uses the full step $x_{k+1} = x_k - \lambda Y_k$.
68: $\lambda=1$ by default, but it can be configured to be a constant damping factor using `-snes_linesearch_damping` or `SNESLineSearchSetDamping()`.
69: Thus, this routine is intended for methods with well-scaled updates; i.e. Newton's method (`SNESNEWTONLS`), on
70: well-behaved problems.
72: Options Database Keys:
73: + -snes_linesearch_damping damping - step length is scaled by this factor, i.e. this is the $\lambda$ above
74: - -snes_linesearch_norms (true|false) - whether to compute norms or not (`SNESLineSearchSetComputeNorms()`)
76: Level: advanced
78: Note:
79: For methods with ill-scaled updates (`SNESNRICHARDSON`, `SNESNCG`), a small
80: damping parameter may yield satisfactory, but slow convergence, despite
81: the lack of the line search.
83: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchSetDamping()`, `SNESLineSearchSetComputeNorms()`
84: M*/
85: PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_None(SNESLineSearch linesearch)
86: {
87: PetscFunctionBegin;
88: linesearch->ops->apply = SNESLineSearchApply_None;
89: linesearch->ops->destroy = NULL;
90: linesearch->ops->setfromoptions = NULL;
91: linesearch->ops->reset = NULL;
92: linesearch->ops->view = SNESLineSearchView_None;
93: linesearch->ops->setup = NULL;
94: PetscFunctionReturn(PETSC_SUCCESS);
95: }