xref: /petsc/src/snes/linesearch/impls/nleqerr/linesearchnleqerr.c (revision d4c6564c171d7f6bffed680177fba1cf86876815)
1*d4c6564cSPatrick Farrell #include <petsc-private/linesearchimpl.h> /*I  "petscsnes.h"  I*/
2*d4c6564cSPatrick Farrell #include <petsc-private/snesimpl.h>
3*d4c6564cSPatrick Farrell 
4*d4c6564cSPatrick Farrell typedef struct {
5*d4c6564cSPatrick Farrell   PetscReal norm_delta_x_prev; /* norm of previous update */
6*d4c6564cSPatrick Farrell   PetscReal norm_bar_delta_x_prev; /* norm of previous bar update */
7*d4c6564cSPatrick Farrell   PetscReal mu_curr; /* current local Lipschitz estimate */
8*d4c6564cSPatrick Farrell   PetscReal lambda_prev; /* previous step length: for some reason SNESLineSearchGetLambda returns 1 instead of the previous step length */
9*d4c6564cSPatrick Farrell } SNESLineSearch_NLEQERR;
10*d4c6564cSPatrick Farrell 
11*d4c6564cSPatrick Farrell PetscBool NLEQERR_cited = PETSC_FALSE;
12*d4c6564cSPatrick Farrell const char NLEQERR_citation[] = "@book{deuflhard2011,\n"
13*d4c6564cSPatrick Farrell                                "  title = {Newton Methods for Nonlinear Problems},\n"
14*d4c6564cSPatrick Farrell                                "  author = {Peter Deuflhard},\n"
15*d4c6564cSPatrick Farrell                                "  volume = 35,\n"
16*d4c6564cSPatrick Farrell                                "  year = 2011,\n"
17*d4c6564cSPatrick Farrell                                "  isbn = {978-3-642-23898-7},\n"
18*d4c6564cSPatrick Farrell                                "  doi  = {10.1007/978-3-642-23899-4},\n"
19*d4c6564cSPatrick Farrell                                "  publisher = {Springer-Verlag},\n"
20*d4c6564cSPatrick Farrell                                "  address = {Berlin, Heidelberg}\n}\n";
21*d4c6564cSPatrick Farrell 
22*d4c6564cSPatrick Farrell #undef __FUNCT__
23*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchApply_NLEQERR"
24*d4c6564cSPatrick Farrell static PetscErrorCode  SNESLineSearchApply_NLEQERR(SNESLineSearch linesearch)
25*d4c6564cSPatrick Farrell {
26*d4c6564cSPatrick Farrell   PetscBool         changed_y,changed_w;
27*d4c6564cSPatrick Farrell   PetscErrorCode    ierr;
28*d4c6564cSPatrick Farrell   Vec               X,F,Y,W,G;
29*d4c6564cSPatrick Farrell   SNES              snes;
30*d4c6564cSPatrick Farrell   PetscReal         fnorm, xnorm, ynorm, gnorm, wnorm;
31*d4c6564cSPatrick Farrell   PetscReal         lambda, minlambda, stol;
32*d4c6564cSPatrick Farrell   PetscViewer       monitor;
33*d4c6564cSPatrick Farrell   PetscInt          max_its,count;
34*d4c6564cSPatrick Farrell   PetscReal         theta, mudash, lambdadash;
35*d4c6564cSPatrick Farrell   SNESLineSearch_NLEQERR *nleqerr;
36*d4c6564cSPatrick Farrell   KSPConvergedReason kspreason;
37*d4c6564cSPatrick Farrell 
38*d4c6564cSPatrick Farrell   PetscFunctionBegin;
39*d4c6564cSPatrick Farrell   ierr = PetscCitationsRegister(NLEQERR_citation, &NLEQERR_cited);CHKERRQ(ierr);
40*d4c6564cSPatrick Farrell 
41*d4c6564cSPatrick Farrell   ierr = SNESLineSearchGetVecs(linesearch, &X, &F, &Y, &W, &G);CHKERRQ(ierr);
42*d4c6564cSPatrick Farrell   ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr);
43*d4c6564cSPatrick Farrell   ierr = SNESLineSearchGetLambda(linesearch, &lambda);CHKERRQ(ierr);
44*d4c6564cSPatrick Farrell   ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr);
45*d4c6564cSPatrick Farrell   ierr = SNESLineSearchGetMonitor(linesearch, &monitor);CHKERRQ(ierr);
46*d4c6564cSPatrick Farrell   ierr = SNESLineSearchGetTolerances(linesearch,&minlambda,NULL,NULL,NULL,NULL,&max_its);CHKERRQ(ierr);
47*d4c6564cSPatrick Farrell   ierr = SNESGetTolerances(snes,NULL,NULL,&stol,NULL,NULL);CHKERRQ(ierr);
48*d4c6564cSPatrick Farrell   nleqerr   = (SNESLineSearch_NLEQERR*)linesearch->data;
49*d4c6564cSPatrick Farrell 
50*d4c6564cSPatrick Farrell   /* precheck */
51*d4c6564cSPatrick Farrell   ierr = SNESLineSearchPreCheck(linesearch,X,Y,&changed_y);CHKERRQ(ierr);
52*d4c6564cSPatrick Farrell   ierr = SNESLineSearchSetSuccess(linesearch, PETSC_TRUE);CHKERRQ(ierr);
53*d4c6564cSPatrick Farrell 
54*d4c6564cSPatrick Farrell   ierr = VecNormBegin(Y, NORM_2, &ynorm);CHKERRQ(ierr);
55*d4c6564cSPatrick Farrell   ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr);
56*d4c6564cSPatrick Farrell   ierr = VecNormEnd(Y, NORM_2, &ynorm);CHKERRQ(ierr);
57*d4c6564cSPatrick Farrell   ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr);
58*d4c6564cSPatrick Farrell 
59*d4c6564cSPatrick Farrell   /* Note: Y is *minus* the Newton step. For whatever reason PETSc doesn't solve with the minus on
60*d4c6564cSPatrick Farrell      the RHS. */
61*d4c6564cSPatrick Farrell 
62*d4c6564cSPatrick Farrell   if (ynorm == 0.0) {
63*d4c6564cSPatrick Farrell     if (monitor) {
64*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
65*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIPrintf(monitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
66*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
67*d4c6564cSPatrick Farrell     }
68*d4c6564cSPatrick Farrell     ierr = VecCopy(X,W);CHKERRQ(ierr);
69*d4c6564cSPatrick Farrell     ierr = VecCopy(F,G);CHKERRQ(ierr);
70*d4c6564cSPatrick Farrell     ierr = SNESLineSearchSetNorms(linesearch,xnorm,fnorm,ynorm);CHKERRQ(ierr);
71*d4c6564cSPatrick Farrell     ierr = SNESLineSearchSetSuccess(linesearch, PETSC_FALSE);CHKERRQ(ierr);
72*d4c6564cSPatrick Farrell     PetscFunctionReturn(0);
73*d4c6564cSPatrick Farrell   }
74*d4c6564cSPatrick Farrell 
75*d4c6564cSPatrick Farrell   /* At this point, we've solved the Newton system for delta_x, and we assume that
76*d4c6564cSPatrick Farrell      its norm is greater than the solution tolerance (otherwise we wouldn't be in
77*d4c6564cSPatrick Farrell      here). So let's go ahead and estimate the Lipschitz constant.
78*d4c6564cSPatrick Farrell 
79*d4c6564cSPatrick Farrell      W contains bar_delta_x_prev at this point. */
80*d4c6564cSPatrick Farrell 
81*d4c6564cSPatrick Farrell   if (monitor) {
82*d4c6564cSPatrick Farrell     ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
83*d4c6564cSPatrick Farrell     ierr = PetscViewerASCIIPrintf(monitor,"    Line search: norm of Newton step: %14.12e\n", (double) ynorm);CHKERRQ(ierr);
84*d4c6564cSPatrick Farrell     ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
85*d4c6564cSPatrick Farrell   }
86*d4c6564cSPatrick Farrell 
87*d4c6564cSPatrick Farrell   /* this needs information from a previous iteration, so can't do it on the first one */
88*d4c6564cSPatrick Farrell   if (nleqerr->norm_delta_x_prev > 0 && nleqerr->norm_bar_delta_x_prev > 0) {
89*d4c6564cSPatrick Farrell     ierr = VecWAXPY(G, +1.0, Y, W);CHKERRQ(ierr); /* bar_delta_x - delta_x; +1 because Y is -delta_x */
90*d4c6564cSPatrick Farrell     ierr = VecNormBegin(G, NORM_2, &gnorm);CHKERRQ(ierr);
91*d4c6564cSPatrick Farrell     ierr = VecNormEnd(G, NORM_2, &gnorm);CHKERRQ(ierr);
92*d4c6564cSPatrick Farrell 
93*d4c6564cSPatrick Farrell     nleqerr->mu_curr = nleqerr->lambda_prev * (nleqerr->norm_delta_x_prev * nleqerr->norm_bar_delta_x_prev) / (gnorm * ynorm);
94*d4c6564cSPatrick Farrell     lambda = PetscMin(1.0, nleqerr->mu_curr);
95*d4c6564cSPatrick Farrell 
96*d4c6564cSPatrick Farrell     if (monitor) {
97*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
98*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIPrintf(monitor,"    Line search: Lipschitz estimate: %14.12e; lambda: %14.12e\n", (double) nleqerr->mu_curr, (double) lambda);CHKERRQ(ierr);
99*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
100*d4c6564cSPatrick Farrell     }
101*d4c6564cSPatrick Farrell   }
102*d4c6564cSPatrick Farrell   else {
103*d4c6564cSPatrick Farrell     lambda = linesearch->damping;
104*d4c6564cSPatrick Farrell   }
105*d4c6564cSPatrick Farrell 
106*d4c6564cSPatrick Farrell 
107*d4c6564cSPatrick Farrell   /* The main while loop of the algorithm.
108*d4c6564cSPatrick Farrell      At the end of this while loop, G should have the accepted new X in it. */
109*d4c6564cSPatrick Farrell 
110*d4c6564cSPatrick Farrell   count = 0;
111*d4c6564cSPatrick Farrell   while (true) {
112*d4c6564cSPatrick Farrell     if (monitor) {
113*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
114*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIPrintf(monitor,"    Line search: entering iteration with lambda: %14.12e\n", lambda);CHKERRQ(ierr);
115*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
116*d4c6564cSPatrick Farrell     }
117*d4c6564cSPatrick Farrell 
118*d4c6564cSPatrick Farrell     /* Check that we haven't performed too many iterations */
119*d4c6564cSPatrick Farrell     count += 1;
120*d4c6564cSPatrick Farrell     if (count >= max_its)
121*d4c6564cSPatrick Farrell     {
122*d4c6564cSPatrick Farrell       if (monitor) {
123*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
124*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIIPrintf(monitor,"    Line search: maximum iterations reached\n");CHKERRQ(ierr);
125*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
126*d4c6564cSPatrick Farrell       }
127*d4c6564cSPatrick Farrell       ierr = SNESLineSearchSetSuccess(linesearch, PETSC_FALSE);CHKERRQ(ierr);
128*d4c6564cSPatrick Farrell       PetscFunctionReturn(0);
129*d4c6564cSPatrick Farrell     }
130*d4c6564cSPatrick Farrell 
131*d4c6564cSPatrick Farrell     /* Now comes the Regularity Test. */
132*d4c6564cSPatrick Farrell     if (lambda <= minlambda) {
133*d4c6564cSPatrick Farrell       /* This isn't what is suggested by Deuflhard, but it works better in my experience */
134*d4c6564cSPatrick Farrell       if (monitor) {
135*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
136*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIIPrintf(monitor,"    Line search: lambda has reached lambdamin, taking full Newton step\n");CHKERRQ(ierr);
137*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
138*d4c6564cSPatrick Farrell       }
139*d4c6564cSPatrick Farrell       lambda = 1.0;
140*d4c6564cSPatrick Farrell       ierr = VecWAXPY(G, -lambda, Y, X);CHKERRQ(ierr);
141*d4c6564cSPatrick Farrell       break;
142*d4c6564cSPatrick Farrell     }
143*d4c6564cSPatrick Farrell 
144*d4c6564cSPatrick Farrell     /* Compute new trial iterate */
145*d4c6564cSPatrick Farrell     ierr = VecWAXPY(W, -lambda, Y, X);CHKERRQ(ierr);
146*d4c6564cSPatrick Farrell     ierr = SNESComputeFunction(snes, W, G);CHKERRQ(ierr);
147*d4c6564cSPatrick Farrell 
148*d4c6564cSPatrick Farrell     /* Solve linear system for bar_delta_x_curr: old Jacobian, new RHS. Note absence of minus sign, compared to Deuflhard, in keeping with PETSc convention */
149*d4c6564cSPatrick Farrell     ierr = KSPSolve(snes->ksp, G, W);CHKERRQ(ierr);
150*d4c6564cSPatrick Farrell     ierr = KSPGetConvergedReason(snes->ksp, &kspreason);CHKERRQ(ierr);
151*d4c6564cSPatrick Farrell     if (kspreason < 0) {
152*d4c6564cSPatrick Farrell       ierr = PetscInfo(snes,"Solution for \\bar{delta x}^{k+1} failed.");CHKERRQ(ierr);
153*d4c6564cSPatrick Farrell     }
154*d4c6564cSPatrick Farrell 
155*d4c6564cSPatrick Farrell     /* W now contains -bar_delta_x_curr. */
156*d4c6564cSPatrick Farrell 
157*d4c6564cSPatrick Farrell     ierr = VecNorm(W, NORM_2, &wnorm);CHKERRQ(ierr);
158*d4c6564cSPatrick Farrell     if (monitor) {
159*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
160*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIIPrintf(monitor,"    Line search: norm of simplified Newton update: %14.12e\n", (double) wnorm);CHKERRQ(ierr);
161*d4c6564cSPatrick Farrell       ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
162*d4c6564cSPatrick Farrell     }
163*d4c6564cSPatrick Farrell 
164*d4c6564cSPatrick Farrell     /* compute the monitoring quantities theta and mudash. */
165*d4c6564cSPatrick Farrell 
166*d4c6564cSPatrick Farrell     theta = wnorm / ynorm;
167*d4c6564cSPatrick Farrell 
168*d4c6564cSPatrick Farrell     ierr = VecWAXPY(G, -(1.0 - lambda), Y, W);CHKERRQ(ierr);
169*d4c6564cSPatrick Farrell     ierr = VecNorm(G, NORM_2, &gnorm);CHKERRQ(ierr);
170*d4c6564cSPatrick Farrell 
171*d4c6564cSPatrick Farrell     mudash = (0.5 * ynorm * lambda * lambda) / gnorm;
172*d4c6564cSPatrick Farrell 
173*d4c6564cSPatrick Farrell     /* Check for termination of the linesearch */
174*d4c6564cSPatrick Farrell     if (theta >= 1.0) {
175*d4c6564cSPatrick Farrell       /* need to go around again with smaller lambda */
176*d4c6564cSPatrick Farrell       if (monitor) {
177*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
178*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIIPrintf(monitor,"    Line search: monotonicity check failed, ratio: %14.12e\n", (double) theta);CHKERRQ(ierr);
179*d4c6564cSPatrick Farrell         ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr);
180*d4c6564cSPatrick Farrell       }
181*d4c6564cSPatrick Farrell       lambda = PetscMin(mudash, 0.5 * lambda);
182*d4c6564cSPatrick Farrell       lambda = PetscMax(lambda, minlambda);
183*d4c6564cSPatrick Farrell       /* continue through the loop, i.e. go back to regularity test */
184*d4c6564cSPatrick Farrell     }
185*d4c6564cSPatrick Farrell     else {
186*d4c6564cSPatrick Farrell       /* linesearch terminated */
187*d4c6564cSPatrick Farrell       lambdadash = PetscMin(1.0, mudash);
188*d4c6564cSPatrick Farrell 
189*d4c6564cSPatrick Farrell       if (lambdadash == 1.0 && lambda == 1.0 && wnorm <= stol) {
190*d4c6564cSPatrick Farrell         /* store the updated state, X - Y - W, in G:
191*d4c6564cSPatrick Farrell            I need to keep W for the next linesearch */
192*d4c6564cSPatrick Farrell         ierr = VecZeroEntries(G);CHKERRQ(ierr);
193*d4c6564cSPatrick Farrell         ierr = VecAXPY(G, +1.0, X);CHKERRQ(ierr);
194*d4c6564cSPatrick Farrell         ierr = VecAXPY(G, -1.0, Y);CHKERRQ(ierr);
195*d4c6564cSPatrick Farrell         ierr = VecAXPY(G, -1.0, W);CHKERRQ(ierr);
196*d4c6564cSPatrick Farrell         break;
197*d4c6564cSPatrick Farrell       }
198*d4c6564cSPatrick Farrell 
199*d4c6564cSPatrick Farrell       /* Deuflhard suggests to add the following:
200*d4c6564cSPatrick Farrell       else if (lambdadash >= 4.0 * lambda) {
201*d4c6564cSPatrick Farrell         lambda = lambdadash;
202*d4c6564cSPatrick Farrell       }
203*d4c6564cSPatrick Farrell       to continue through the loop, i.e. go back to regularity test.
204*d4c6564cSPatrick Farrell       I deliberately exclude this, as I have practical experience of this
205*d4c6564cSPatrick Farrell       getting stuck in infinite loops (on e.g. an Allen--Cahn problem). */
206*d4c6564cSPatrick Farrell 
207*d4c6564cSPatrick Farrell       else {
208*d4c6564cSPatrick Farrell         /* accept iterate without adding on, i.e. don't use bar_delta_x;
209*d4c6564cSPatrick Farrell            again, I need to keep W for the next linesearch */
210*d4c6564cSPatrick Farrell         ierr = VecWAXPY(G, -lambda, Y, X);CHKERRQ(ierr);
211*d4c6564cSPatrick Farrell         break;
212*d4c6564cSPatrick Farrell       }
213*d4c6564cSPatrick Farrell     }
214*d4c6564cSPatrick Farrell   }
215*d4c6564cSPatrick Farrell 
216*d4c6564cSPatrick Farrell   if (linesearch->ops->viproject) {
217*d4c6564cSPatrick Farrell     ierr = (*linesearch->ops->viproject)(snes, G);CHKERRQ(ierr);
218*d4c6564cSPatrick Farrell   }
219*d4c6564cSPatrick Farrell 
220*d4c6564cSPatrick Farrell   /* W currently contains -bar_delta_u. Scale it so that it contains bar_delta_u. */
221*d4c6564cSPatrick Farrell   ierr = VecScale(W, -1.0);CHKERRQ(ierr);
222*d4c6564cSPatrick Farrell 
223*d4c6564cSPatrick Farrell   /* postcheck */
224*d4c6564cSPatrick Farrell   ierr = SNESLineSearchPostCheck(linesearch,X,Y,G,&changed_y,&changed_w);CHKERRQ(ierr);
225*d4c6564cSPatrick Farrell   if (changed_y || changed_w) {
226*d4c6564cSPatrick Farrell     ierr = SNESLineSearchSetSuccess(linesearch, PETSC_FALSE);CHKERRQ(ierr);
227*d4c6564cSPatrick Farrell     ierr = PetscInfo(snes,"Changing the search direction here doesn't make sense.\n");CHKERRQ(ierr);
228*d4c6564cSPatrick Farrell     PetscFunctionReturn(0);
229*d4c6564cSPatrick Farrell   }
230*d4c6564cSPatrick Farrell 
231*d4c6564cSPatrick Farrell   /* copy the solution and information from this iteration over */
232*d4c6564cSPatrick Farrell   nleqerr->norm_delta_x_prev = ynorm;
233*d4c6564cSPatrick Farrell   nleqerr->norm_bar_delta_x_prev = wnorm;
234*d4c6564cSPatrick Farrell   nleqerr->lambda_prev = lambda;
235*d4c6564cSPatrick Farrell 
236*d4c6564cSPatrick Farrell   ierr = VecCopy(G, X);CHKERRQ(ierr);
237*d4c6564cSPatrick Farrell   ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
238*d4c6564cSPatrick Farrell   ierr = VecNorm(X, NORM_2, &xnorm);CHKERRQ(ierr);
239*d4c6564cSPatrick Farrell   ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr);
240*d4c6564cSPatrick Farrell   ierr = SNESLineSearchSetLambda(linesearch, lambda);CHKERRQ(ierr);
241*d4c6564cSPatrick Farrell   ierr = SNESLineSearchSetNorms(linesearch, xnorm, fnorm, ynorm);CHKERRQ(ierr);
242*d4c6564cSPatrick Farrell   PetscFunctionReturn(0);
243*d4c6564cSPatrick Farrell }
244*d4c6564cSPatrick Farrell 
245*d4c6564cSPatrick Farrell #undef __FUNCT__
246*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchView_NLEQERR"
247*d4c6564cSPatrick Farrell PetscErrorCode SNESLineSearchView_NLEQERR(SNESLineSearch linesearch, PetscViewer viewer)
248*d4c6564cSPatrick Farrell {
249*d4c6564cSPatrick Farrell   PetscErrorCode          ierr;
250*d4c6564cSPatrick Farrell   PetscBool               iascii;
251*d4c6564cSPatrick Farrell   SNESLineSearch_NLEQERR *nleqerr;
252*d4c6564cSPatrick Farrell 
253*d4c6564cSPatrick Farrell   PetscFunctionBegin;
254*d4c6564cSPatrick Farrell   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
255*d4c6564cSPatrick Farrell   nleqerr   = (SNESLineSearch_NLEQERR*)linesearch->data;
256*d4c6564cSPatrick Farrell   if (iascii) {
257*d4c6564cSPatrick Farrell     ierr = PetscViewerASCIIPrintf(viewer, "  NLEQ-ERR affine-covariant linesearch");CHKERRQ(ierr);
258*d4c6564cSPatrick Farrell     ierr = PetscViewerASCIIPrintf(viewer, "  current local Lipschitz estimate omega=%e\n", (double)nleqerr->mu_curr);CHKERRQ(ierr);
259*d4c6564cSPatrick Farrell   }
260*d4c6564cSPatrick Farrell   PetscFunctionReturn(0);
261*d4c6564cSPatrick Farrell }
262*d4c6564cSPatrick Farrell 
263*d4c6564cSPatrick Farrell #undef __FUNCT__
264*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchDestroy_NLEQERR"
265*d4c6564cSPatrick Farrell static PetscErrorCode SNESLineSearchDestroy_NLEQERR(SNESLineSearch linesearch)
266*d4c6564cSPatrick Farrell {
267*d4c6564cSPatrick Farrell   PetscErrorCode ierr;
268*d4c6564cSPatrick Farrell 
269*d4c6564cSPatrick Farrell   PetscFunctionBegin;
270*d4c6564cSPatrick Farrell   ierr = PetscFree(linesearch->data);CHKERRQ(ierr);
271*d4c6564cSPatrick Farrell   PetscFunctionReturn(0);
272*d4c6564cSPatrick Farrell }
273*d4c6564cSPatrick Farrell 
274*d4c6564cSPatrick Farrell #undef __FUNCT__
275*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchReset_NLEQERR"
276*d4c6564cSPatrick Farrell static PetscErrorCode SNESLineSearchReset_NLEQERR(SNESLineSearch linesearch)
277*d4c6564cSPatrick Farrell {
278*d4c6564cSPatrick Farrell   SNESLineSearch_NLEQERR *nleqerr;
279*d4c6564cSPatrick Farrell 
280*d4c6564cSPatrick Farrell   nleqerr   = (SNESLineSearch_NLEQERR*)linesearch->data;
281*d4c6564cSPatrick Farrell   nleqerr->mu_curr    = 0.0;
282*d4c6564cSPatrick Farrell   nleqerr->norm_delta_x_prev = -1.0;
283*d4c6564cSPatrick Farrell   nleqerr->norm_bar_delta_x_prev = -1.0;
284*d4c6564cSPatrick Farrell   PetscFunctionReturn(0);
285*d4c6564cSPatrick Farrell }
286*d4c6564cSPatrick Farrell 
287*d4c6564cSPatrick Farrell #undef __FUNCT__
288*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchCreate_NLEQERR"
289*d4c6564cSPatrick Farrell /*MC
290*d4c6564cSPatrick Farrell    SNESLINESEARCHNLEQERR - Error-oriented affine-covariant globalised Newton algorithm of Deuflhard (2011).
291*d4c6564cSPatrick Farrell 
292*d4c6564cSPatrick Farrell    This linesearch is intended for Newton-type methods which are affine covariant. Affine covariance
293*d4c6564cSPatrick Farrell    means that Newton's method will give the same iterations for F(x) = 0 and AF(x) = 0 for a nonsingular
294*d4c6564cSPatrick Farrell    matrix A. This is a fundamental property; the philosophy of this linesearch is that globalisations
295*d4c6564cSPatrick Farrell    of Newton's method should carefully preserve it.
296*d4c6564cSPatrick Farrell 
297*d4c6564cSPatrick Farrell    For a discussion of the theory behind this algorithm, see
298*d4c6564cSPatrick Farrell 
299*d4c6564cSPatrick Farrell    @book{deuflhard2011,
300*d4c6564cSPatrick Farrell      title={Newton Methods for Nonlinear Problems},
301*d4c6564cSPatrick Farrell      author={Deuflhard, P.},
302*d4c6564cSPatrick Farrell      volume={35},
303*d4c6564cSPatrick Farrell      year={2011},
304*d4c6564cSPatrick Farrell      publisher={Springer-Verlag},
305*d4c6564cSPatrick Farrell      address={Berlin, Heidelberg}
306*d4c6564cSPatrick Farrell    }
307*d4c6564cSPatrick Farrell 
308*d4c6564cSPatrick Farrell    Pseudocode is given on page 148.
309*d4c6564cSPatrick Farrell 
310*d4c6564cSPatrick Farrell    Options Database Keys:
311*d4c6564cSPatrick Farrell +  -snes_linesearch_damping<1.0> - initial step length
312*d4c6564cSPatrick Farrell -  -snes_linesearch_minlambda<1e-12> - minimum step length allowed
313*d4c6564cSPatrick Farrell 
314*d4c6564cSPatrick Farrell    Contributed by Patrick Farrell <patrick.farrell@maths.ox.ac.uk>
315*d4c6564cSPatrick Farrell 
316*d4c6564cSPatrick Farrell    Level: advanced
317*d4c6564cSPatrick Farrell 
318*d4c6564cSPatrick Farrell .keywords: SNES, SNESLineSearch, damping
319*d4c6564cSPatrick Farrell 
320*d4c6564cSPatrick Farrell .seealso: SNESLineSearchCreate(), SNESLineSearchSetType()
321*d4c6564cSPatrick Farrell M*/
322*d4c6564cSPatrick Farrell PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_NLEQERR(SNESLineSearch linesearch)
323*d4c6564cSPatrick Farrell {
324*d4c6564cSPatrick Farrell 
325*d4c6564cSPatrick Farrell   SNESLineSearch_NLEQERR *nleqerr;
326*d4c6564cSPatrick Farrell   PetscErrorCode    ierr;
327*d4c6564cSPatrick Farrell 
328*d4c6564cSPatrick Farrell   PetscFunctionBegin;
329*d4c6564cSPatrick Farrell   linesearch->ops->apply          = SNESLineSearchApply_NLEQERR;
330*d4c6564cSPatrick Farrell   linesearch->ops->destroy        = SNESLineSearchDestroy_NLEQERR;
331*d4c6564cSPatrick Farrell   linesearch->ops->setfromoptions = NULL;
332*d4c6564cSPatrick Farrell   linesearch->ops->reset          = SNESLineSearchReset_NLEQERR;
333*d4c6564cSPatrick Farrell   linesearch->ops->view           = SNESLineSearchView_NLEQERR;
334*d4c6564cSPatrick Farrell   linesearch->ops->setup          = NULL;
335*d4c6564cSPatrick Farrell 
336*d4c6564cSPatrick Farrell   ierr = PetscNewLog(linesearch,&nleqerr);CHKERRQ(ierr);
337*d4c6564cSPatrick Farrell 
338*d4c6564cSPatrick Farrell   linesearch->data    = (void*)nleqerr;
339*d4c6564cSPatrick Farrell   linesearch->max_its = 40;
340*d4c6564cSPatrick Farrell   nleqerr->mu_curr    = 0.0;
341*d4c6564cSPatrick Farrell   nleqerr->norm_delta_x_prev = -1.0;
342*d4c6564cSPatrick Farrell   nleqerr->norm_bar_delta_x_prev = -1.0;
343*d4c6564cSPatrick Farrell   PetscFunctionReturn(0);
344*d4c6564cSPatrick Farrell }
345