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