xref: /petsc/src/snes/linesearch/impls/basic/linesearchbasic.c (revision 1d27aa22b2f6148b2c4e3f06a75e0638d6493e09)
1 #include <petsc/private/linesearchimpl.h>
2 #include <petsc/private/snesimpl.h>
3 
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;
11 
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));
18 
19   /* precheck */
20   PetscCall(SNESLineSearchPreCheck(linesearch, X, Y, &changed_y));
21 
22   /* update */
23   PetscCall(VecWAXPY(W, -lambda, Y, X));
24   if (linesearch->ops->viproject) PetscCall((*linesearch->ops->viproject)(snes, W));
25 
26   /* postcheck */
27   PetscCall(SNESLineSearchPostCheck(linesearch, X, Y, W, &changed_y, &changed_w));
28   if (changed_y && !changed_w) {
29     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 
41   if (linesearch->norms) {
42     if (!linesearch->ops->vinorm) PetscCall(VecNormBegin(F, NORM_2, &linesearch->fnorm));
43     PetscCall(VecNormBegin(Y, NORM_2, &linesearch->ynorm));
44     PetscCall(VecNormBegin(W, NORM_2, &linesearch->xnorm));
45     if (!linesearch->ops->vinorm) PetscCall(VecNormEnd(F, NORM_2, &linesearch->fnorm));
46     PetscCall(VecNormEnd(Y, NORM_2, &linesearch->ynorm));
47     PetscCall(VecNormEnd(W, NORM_2, &linesearch->xnorm));
48 
49     if (linesearch->ops->vinorm) {
50       linesearch->fnorm = gnorm;
51 
52       PetscCall((*linesearch->ops->vinorm)(snes, F, W, &linesearch->fnorm));
53     } else {
54       PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm));
55     }
56   }
57 
58   /* copy the solution over */
59   PetscCall(VecCopy(W, X));
60   PetscFunctionReturn(PETSC_SUCCESS);
61 }
62 
63 /*MC
64    SNESLINESEARCHBASIC - This line search implementation is not a line
65    search at all; it simply uses the full step.  Thus, this routine is intended
66    for methods with well-scaled updates; i.e. Newton's method (`SNESNEWTONLS`), on
67    well-behaved problems. Also named as `SNESLINESEARCHNONE`
68 
69    Options Database Keys:
70 +   -snes_linesearch_damping <damping> - search vector is scaled by this amount, default is 1.0
71 -   -snes_linesearch_norms <flag> - whether to compute norms or not, default is true (SNESLineSearchSetComputeNorms())
72 
73    Note:
74    For methods with ill-scaled updates (`SNESNRICHARDSON`, `SNESNCG`), a small
75    damping parameter may yield satisfactory but slow convergence despite
76    the lack of the line search.
77 
78    Level: advanced
79 
80 .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchSetDamping()`, `SNESLineSearchSetComputeNorms()`
81 M*/
82 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Basic(SNESLineSearch linesearch)
83 {
84   PetscFunctionBegin;
85   linesearch->ops->apply          = SNESLineSearchApply_Basic;
86   linesearch->ops->destroy        = NULL;
87   linesearch->ops->setfromoptions = NULL;
88   linesearch->ops->reset          = NULL;
89   linesearch->ops->view           = NULL;
90   linesearch->ops->setup          = NULL;
91   PetscFunctionReturn(PETSC_SUCCESS);
92 }
93