xref: /petsc/src/snes/linesearch/impls/basic/linesearchbasic.c (revision f6dfbefd03961ab3be6f06be75c96cbf27a49667)
1af0996ceSBarry Smith #include <petsc/private/linesearchimpl.h>
2af0996ceSBarry Smith #include <petsc/private/snesimpl.h>
3bf7f4e0aSPeter Brune 
49371c9d4SSatish Balay static PetscErrorCode SNESLineSearchApply_Basic(SNESLineSearch linesearch) {
5bf7f4e0aSPeter Brune   PetscBool changed_y, changed_w;
66a388c36SPeter Brune   Vec       X, F, Y, W;
76a388c36SPeter Brune   SNES      snes;
86a388c36SPeter Brune   PetscReal gnorm, xnorm, ynorm, lambda;
96a388c36SPeter Brune   PetscBool domainerror;
10bf7f4e0aSPeter Brune 
11bf7f4e0aSPeter Brune   PetscFunctionBegin;
129566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchGetVecs(linesearch, &X, &F, &Y, &W, NULL));
139566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchGetNorms(linesearch, &xnorm, &gnorm, &ynorm));
149566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchGetLambda(linesearch, &lambda));
159566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
169566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_SUCCEEDED));
17bf7f4e0aSPeter Brune 
18bf7f4e0aSPeter Brune   /* precheck */
199566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchPreCheck(linesearch, X, Y, &changed_y));
20bf7f4e0aSPeter Brune 
21bf7f4e0aSPeter Brune   /* update */
229566063dSJacob Faibussowitsch   PetscCall(VecWAXPY(W, -lambda, Y, X));
231baa6e33SBarry Smith   if (linesearch->ops->viproject) PetscCall((*linesearch->ops->viproject)(snes, W));
24bf7f4e0aSPeter Brune 
25bf7f4e0aSPeter Brune   /* postcheck */
269566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchPostCheck(linesearch, X, Y, W, &changed_y, &changed_w));
27bf7f4e0aSPeter Brune   if (changed_y) {
289566063dSJacob Faibussowitsch     PetscCall(VecWAXPY(W, -lambda, Y, X));
291baa6e33SBarry Smith     if (linesearch->ops->viproject) PetscCall((*linesearch->ops->viproject)(snes, W));
30bf7f4e0aSPeter Brune   }
315fc09b23SPeter Brune   if (linesearch->norms || snes->iter < snes->max_its - 1) {
329566063dSJacob Faibussowitsch     PetscCall((*linesearch->ops->snesfunc)(snes, W, F));
339566063dSJacob Faibussowitsch     PetscCall(SNESGetFunctionDomainError(snes, &domainerror));
346a388c36SPeter Brune     if (domainerror) {
359566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_DOMAIN));
36bf7f4e0aSPeter Brune       PetscFunctionReturn(0);
37bf7f4e0aSPeter Brune     }
385fc09b23SPeter Brune   }
396a388c36SPeter Brune 
405fc09b23SPeter Brune   if (linesearch->norms) {
419566063dSJacob Faibussowitsch     if (!linesearch->ops->vinorm) PetscCall(VecNormBegin(F, NORM_2, &linesearch->fnorm));
429566063dSJacob Faibussowitsch     PetscCall(VecNormBegin(Y, NORM_2, &linesearch->ynorm));
439566063dSJacob Faibussowitsch     PetscCall(VecNormBegin(W, NORM_2, &linesearch->xnorm));
449566063dSJacob Faibussowitsch     if (!linesearch->ops->vinorm) PetscCall(VecNormEnd(F, NORM_2, &linesearch->fnorm));
459566063dSJacob Faibussowitsch     PetscCall(VecNormEnd(Y, NORM_2, &linesearch->ynorm));
469566063dSJacob Faibussowitsch     PetscCall(VecNormEnd(W, NORM_2, &linesearch->xnorm));
475fc09b23SPeter Brune 
489bd66eb0SPeter Brune     if (linesearch->ops->vinorm) {
499bd66eb0SPeter Brune       linesearch->fnorm = gnorm;
50f5af7f23SKarl Rupp 
519566063dSJacob Faibussowitsch       PetscCall((*linesearch->ops->vinorm)(snes, F, W, &linesearch->fnorm));
529bd66eb0SPeter Brune     } else {
539566063dSJacob Faibussowitsch       PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm));
549bd66eb0SPeter Brune     }
555fc09b23SPeter Brune   }
566a388c36SPeter Brune 
57bf7f4e0aSPeter Brune   /* copy the solution over */
589566063dSJacob Faibussowitsch   PetscCall(VecCopy(W, X));
59bf7f4e0aSPeter Brune   PetscFunctionReturn(0);
60bf7f4e0aSPeter Brune }
61bf7f4e0aSPeter Brune 
62954494b2SJed Brown /*MC
631a4f838cSPeter Brune    SNESLINESEARCHBASIC - This line search implementation is not a line
64cd7522eaSPeter Brune    search at all; it simply uses the full step.  Thus, this routine is intended
65*f6dfbefdSBarry Smith    for methods with well-scaled updates; i.e. Newton's method (`SNESNEWTONLS`), on
66*f6dfbefdSBarry Smith    well-behaved problems. Also named as `SNESLINESEARCHNONE`
67cd7522eaSPeter Brune 
68cd7522eaSPeter Brune    Options Database Keys:
697c720adbSBarry Smith +   -snes_linesearch_damping <damping> - search vector is scaled by this amount, default is 1.0
701fe24845SBarry Smith -   -snes_linesearch_norms <flag> - whether to compute norms or not, default is true (SNESLineSearchSetComputeNorms())
71cd7522eaSPeter Brune 
72*f6dfbefdSBarry Smith    Note:
73*f6dfbefdSBarry Smith    For methods with ill-scaled updates (`SNESNRICHARDSON`, `SNESNCG`), a small
74cd7522eaSPeter Brune    damping parameter may yield satisfactory but slow convergence despite
75*f6dfbefdSBarry Smith    the lack of the line search.
76954494b2SJed Brown 
77954494b2SJed Brown    Level: advanced
78954494b2SJed Brown 
79*f6dfbefdSBarry Smith .seealso: `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetType()`, `SNESLineSearchSetDamping()`, `SNESLineSearchSetComputeNorms()`
80954494b2SJed Brown M*/
819371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_Basic(SNESLineSearch linesearch) {
82bf7f4e0aSPeter Brune   PetscFunctionBegin;
83f1c6b773SPeter Brune   linesearch->ops->apply          = SNESLineSearchApply_Basic;
840298fd71SBarry Smith   linesearch->ops->destroy        = NULL;
850298fd71SBarry Smith   linesearch->ops->setfromoptions = NULL;
860298fd71SBarry Smith   linesearch->ops->reset          = NULL;
870298fd71SBarry Smith   linesearch->ops->view           = NULL;
880298fd71SBarry Smith   linesearch->ops->setup          = NULL;
89bf7f4e0aSPeter Brune   PetscFunctionReturn(0);
90bf7f4e0aSPeter Brune }
91