xref: /petsc/src/snes/impls/ls/ls.c (revision 029af93f72d387caa45cf6909ac9aed2d04296ca)
1 #ifndef lint
2 static char vcid[] = "$Id: ls.c,v 1.87 1997/03/20 18:51:55 curfman Exp curfman $";
3 #endif
4 
5 #include <math.h>
6 #include "src/snes/impls/ls/ls.h"
7 #include "pinclude/pviewer.h"
8 
9 /*
10      Implements a line search variant of Newton's Method
11     for solving systems of nonlinear equations.
12 
13     Input parameters:
14 .   snes - nonlinear context obtained from SNESCreate()
15 
16     Output Parameters:
17 .   outits  - Number of global iterations until termination.
18 
19     Notes:
20     This implements essentially a truncated Newton method with a
21     line search.  By default a cubic backtracking line search
22     is employed, as described in the text "Numerical Methods for
23     Unconstrained Optimization and Nonlinear Equations" by Dennis
24     and Schnabel.
25 */
26 
27 #undef __FUNC__
28 #define __FUNC__ "SNESSolve_EQ_LS"
29 int SNESSolve_EQ_LS(SNES snes,int *outits)
30 {
31   SNES_LS       *neP = (SNES_LS *) snes->data;
32   int           maxits, i, history_len, ierr, lits, lsfail;
33   MatStructure  flg = DIFFERENT_NONZERO_PATTERN;
34   double        fnorm, gnorm, xnorm, ynorm, *history;
35   Vec           Y, X, F, G, W, TMP;
36 
37   history	= snes->conv_hist;	/* convergence history */
38   history_len	= snes->conv_hist_size;	/* convergence history length */
39   maxits	= snes->max_its;	/* maximum number of iterations */
40   X		= snes->vec_sol;	/* solution vector */
41   F		= snes->vec_func;	/* residual vector */
42   Y		= snes->work[0];	/* work vectors */
43   G		= snes->work[1];
44   W		= snes->work[2];
45 
46   ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr);       /* xnorm = || X || */
47   snes->iter = 0;
48   ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr);  /*  F(X)      */
49   ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr);	/* fnorm <- ||F||  */
50   snes->norm = fnorm;
51   if (history) history[0] = fnorm;
52   SNESMonitor(snes,0,fnorm);
53 
54   if (fnorm == 0.0) {outits = 0; return 0;}
55 
56   /* set parameter for default relative tolerance convergence test */
57   snes->ttol = fnorm*snes->rtol;
58 
59   for ( i=0; i<maxits; i++ ) {
60     snes->iter = i+1;
61 
62     /* Solve J Y = F, where J is Jacobian matrix */
63     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg); CHKERRQ(ierr);
64     ierr = SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,flg); CHKERRQ(ierr);
65     ierr = SLESSolve(snes->sles,F,Y,&lits); CHKERRQ(ierr);
66     snes->linear_its += PetscAbsInt(lits);
67     PLogInfo(snes,"SNESSolve_EQ_LS: iter=%d, linear solve iterations=%d\n",snes->iter,lits);
68 
69     /* Compute a (scaled) negative update in the line search routine:
70          Y <- X - lambda*Y
71        and evaluate G(Y) = function(Y))
72     */
73     ierr = VecCopy(Y,snes->vec_sol_update_always); CHKERRQ(ierr);
74     ierr = (*neP->LineSearch)(snes,X,F,G,Y,W,fnorm,&ynorm,&gnorm,&lsfail); CHKERRQ(ierr);
75     PLogInfo(snes,"SNESSolve_EQ_LS: fnorm=%g, gnorm=%g, ynorm=%g, lsfail=%d\n",fnorm,gnorm,ynorm,lsfail);
76     if (lsfail) snes->nfailures++;
77 
78     TMP = F; F = G; snes->vec_func_always = F; G = TMP;
79     TMP = X; X = Y; snes->vec_sol_always = X; Y = TMP;
80     fnorm = gnorm;
81 
82     snes->norm = fnorm;
83     if (history && history_len > i+1) history[i+1] = fnorm;
84     ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr);	/* xnorm = || X || */
85     SNESMonitor(snes,i+1,fnorm);
86 
87     /* Test for convergence */
88     if ((*snes->converged)(snes,xnorm,ynorm,fnorm,snes->cnvP)) {
89       break;
90     }
91   }
92   if (X != snes->vec_sol) {
93     ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr);
94     snes->vec_sol_always  = snes->vec_sol;
95     snes->vec_func_always = snes->vec_func;
96   }
97   if (i == maxits) {
98     PLogInfo(snes,
99       "SNESSolve_EQ_LS: Maximum number of iterations has been reached: %d\n",maxits);
100     i--;
101   }
102   if (history) snes->conv_act_size = (history_len < i+1) ? history_len : i+1;
103   *outits = i+1;
104   return 0;
105 }
106 /* ------------------------------------------------------------ */
107 #undef __FUNC__
108 #define __FUNC__ "SNESSetUp_EQ_LS"
109 int SNESSetUp_EQ_LS(SNES snes )
110 {
111   int ierr;
112   snes->nwork = 4;
113   ierr = VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);CHKERRQ(ierr);
114   PLogObjectParents(snes,snes->nwork,snes->work);
115   snes->vec_sol_update_always = snes->work[3];
116   return 0;
117 }
118 /* ------------------------------------------------------------ */
119 #undef __FUNC__
120 #define __FUNC__ "SNESDestroy_EQ_LS" /* ADIC Ignore */
121 int SNESDestroy_EQ_LS(PetscObject obj)
122 {
123   SNES snes = (SNES) obj;
124   int  ierr;
125   if (snes->nwork) {
126     ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr);
127   }
128   PetscFree(snes->data);
129   return 0;
130 }
131 /* ------------------------------------------------------------ */
132 #undef __FUNC__
133 #define __FUNC__ "SNESNoLineSearch"
134 /*ARGSUSED*/
135 /*@C
136    SNESNoLineSearch - This routine is not a line search at all;
137    it simply uses the full Newton step.  Thus, this routine is intended
138    to serve as a template and is not recommended for general use.
139 
140    Input Parameters:
141 .  snes - nonlinear context
142 .  x - current iterate
143 .  f - residual evaluated at x
144 .  y - search direction (contains new iterate on output)
145 .  w - work vector
146 .  fnorm - 2-norm of f
147 
148    Output Parameters:
149 .  g - residual evaluated at new iterate y
150 .  y - new iterate (contains search direction on input)
151 .  gnorm - 2-norm of g
152 .  ynorm - 2-norm of search length
153 .  flag - set to 0, indicating a successful line search
154 
155    Options Database Key:
156 $  -snes_eq_ls basic
157 
158 .keywords: SNES, nonlinear, line search, cubic
159 
160 .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
161           SNESSetLineSearch()
162 @*/
163 int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
164                      double fnorm, double *ynorm, double *gnorm,int *flag )
165 {
166   int    ierr;
167   Scalar mone = -1.0;
168 
169   *flag = 0;
170   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
171   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);       /* ynorm = || y || */
172   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
173   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
174   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);       /* gnorm = || g || */
175   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
176   return 0;
177 }
178 /* ------------------------------------------------------------------ */
179 #undef __FUNC__
180 #define __FUNC__ "SNESCubicLineSearch"
181 /*@C
182    SNESCubicLineSearch - Performs a cubic line search (default line search method).
183 
184    Input Parameters:
185 .  snes - nonlinear context
186 .  x - current iterate
187 .  f - residual evaluated at x
188 .  y - search direction (contains new iterate on output)
189 .  w - work vector
190 .  fnorm - 2-norm of f
191 
192    Output Parameters:
193 .  g - residual evaluated at new iterate y
194 .  y - new iterate (contains search direction on input)
195 .  gnorm - 2-norm of g
196 .  ynorm - 2-norm of search length
197 .  flag - 0 if line search succeeds; -1 on failure.
198 
199    Options Database Key:
200 $  -snes_eq_ls cubic
201 
202    Notes:
203    This line search is taken from "Numerical Methods for Unconstrained
204    Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325.
205 
206 .keywords: SNES, nonlinear, line search, cubic
207 
208 .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
209 @*/
210 int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w,
211                         double fnorm,double *ynorm,double *gnorm,int *flag)
212 {
213   double  steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2;
214   double  maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg;
215 #if defined(PETSC_COMPLEX)
216   Scalar  cinitslope, clambda;
217 #endif
218   int     ierr, count;
219   SNES_LS *neP = (SNES_LS *) snes->data;
220   Scalar  mone = -1.0,scale;
221 
222   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
223   *flag   = 0;
224   alpha   = neP->alpha;
225   maxstep = neP->maxstep;
226   steptol = neP->steptol;
227 
228   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);
229   if (*ynorm == 0.0) {
230     PLogInfo(snes,"SNESCubicLineSearch: Search direction and size is 0\n");
231     goto theend1;
232   }
233   if (*ynorm > maxstep) {	/* Step too big, so scale back */
234     scale = maxstep/(*ynorm);
235 #if defined(PETSC_COMPLEX)
236     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale));
237 #else
238     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale);
239 #endif
240     ierr = VecScale(&scale,y); CHKERRQ(ierr);
241     *ynorm = maxstep;
242   }
243   minlambda = steptol/(*ynorm);
244   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
245 #if defined(PETSC_COMPLEX)
246   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
247   initslope = real(cinitslope);
248 #else
249   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
250 #endif
251   if (initslope > 0.0) initslope = -initslope;
252   if (initslope == 0.0) initslope = -1.0;
253 
254   ierr = VecCopy(y,w); CHKERRQ(ierr);
255   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
256   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
257   ierr = VecNorm(g,NORM_2,gnorm);
258   if (*gnorm <= fnorm + alpha*initslope) {	/* Sufficient reduction */
259     ierr = VecCopy(w,y); CHKERRQ(ierr);
260     PLogInfo(snes,"SNESCubicLineSearch: Using full step\n");
261     goto theend1;
262   }
263 
264   /* Fit points with quadratic */
265   lambda = 1.0; count = 0;
266   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
267   lambdaprev = lambda;
268   gnormprev = *gnorm;
269   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
270   else lambda = lambdatemp;
271   ierr   = VecCopy(x,w); CHKERRQ(ierr);
272   lambdaneg = -lambda;
273 #if defined(PETSC_COMPLEX)
274   clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
275 #else
276   ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
277 #endif
278   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
279   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
280   if (*gnorm <= fnorm + alpha*initslope) {      /* sufficient reduction */
281     ierr = VecCopy(w,y); CHKERRQ(ierr);
282     PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda);
283     goto theend1;
284   }
285 
286   /* Fit points with cubic */
287   count = 1;
288   while (1) {
289     if (lambda <= minlambda) { /* bad luck; use full step */
290       PLogInfo(snes,
291          "SNESCubicLineSearch:Unable to find good step length! %d \n",count);
292       PLogInfo(snes,
293          "SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
294              fnorm,*gnorm,*ynorm,lambda,initslope);
295       ierr = VecCopy(w,y); CHKERRQ(ierr);
296       *flag = -1; break;
297     }
298     t1 = *gnorm - fnorm - lambda*initslope;
299     t2 = gnormprev  - fnorm - lambdaprev*initslope;
300     a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
301     b = (-lambdaprev*t1/(lambda*lambda) +
302                              lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
303     d = b*b - 3*a*initslope;
304     if (d < 0.0) d = 0.0;
305     if (a == 0.0) {
306       lambdatemp = -initslope/(2.0*b);
307     } else {
308       lambdatemp = (-b + sqrt(d))/(3.0*a);
309     }
310     if (lambdatemp > .5*lambda) {
311       lambdatemp = .5*lambda;
312     }
313     lambdaprev = lambda;
314     gnormprev = *gnorm;
315     if (lambdatemp <= .1*lambda) {
316       lambda = .1*lambda;
317     }
318     else lambda = lambdatemp;
319     ierr = VecCopy( x, w ); CHKERRQ(ierr);
320     lambdaneg = -lambda;
321 #if defined(PETSC_COMPLEX)
322     clambda = lambdaneg;
323     ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
324 #else
325     ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
326 #endif
327     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
328     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
329     if (*gnorm <= fnorm + alpha*initslope) {      /* is reduction enough */
330       ierr = VecCopy(w,y); CHKERRQ(ierr);
331       PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda);
332       goto theend1;
333     }
334     count++;
335   }
336   theend1:
337   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
338   return 0;
339 }
340 /* ------------------------------------------------------------------ */
341 #undef __FUNC__
342 #define __FUNC__ "SNESQuadraticLineSearch"
343 /*@C
344    SNESQuadraticLineSearch - Performs a quadratic line search.
345 
346    Input Parameters:
347 .  snes - the SNES context
348 .  x - current iterate
349 .  f - residual evaluated at x
350 .  y - search direction (contains new iterate on output)
351 .  w - work vector
352 .  fnorm - 2-norm of f
353 
354    Output Parameters:
355 .  g - residual evaluated at new iterate y
356 .  y - new iterate (contains search direction on input)
357 .  gnorm - 2-norm of g
358 .  ynorm - 2-norm of search length
359 .  flag - 0 if line search succeeds; -1 on failure.
360 
361    Options Database Key:
362 $  -snes_eq_ls quadratic
363 
364    Notes:
365    Use SNESSetLineSearch()
366    to set this routine within the SNES_EQ_LS method.
367 
368 .keywords: SNES, nonlinear, quadratic, line search
369 
370 .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
371 @*/
372 int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
373                            double fnorm, double *ynorm, double *gnorm,int *flag)
374 {
375   double  steptol,initslope,lambdaprev,gnormprev,maxstep,minlambda,alpha,lambda,lambdatemp;
376 #if defined(PETSC_COMPLEX)
377   Scalar  cinitslope,clambda;
378 #endif
379   int     ierr,count;
380   SNES_LS *neP = (SNES_LS *) snes->data;
381   Scalar  mone = -1.0,scale;
382 
383   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
384   *flag = 0;
385   alpha   = neP->alpha;
386   maxstep = neP->maxstep;
387   steptol = neP->steptol;
388 
389   VecNorm(y, NORM_2,ynorm );
390   if (*ynorm == 0.0) {
391     PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n");
392     goto theend2;
393   }
394   if (*ynorm > maxstep) {	/* Step too big, so scale back */
395     scale = maxstep/(*ynorm);
396     ierr = VecScale(&scale,y); CHKERRQ(ierr);
397     *ynorm = maxstep;
398   }
399   minlambda = steptol/(*ynorm);
400   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
401 #if defined(PETSC_COMPLEX)
402   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
403   initslope = real(cinitslope);
404 #else
405   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
406 #endif
407   if (initslope > 0.0) initslope = -initslope;
408   if (initslope == 0.0) initslope = -1.0;
409 
410   ierr = VecCopy(y,w); CHKERRQ(ierr);
411   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
412   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
413   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
414   if (*gnorm <= fnorm + alpha*initslope) {	/* Sufficient reduction */
415     ierr = VecCopy(w,y); CHKERRQ(ierr);
416     PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n");
417     goto theend2;
418   }
419 
420   /* Fit points with quadratic */
421   lambda = 1.0; count = 0;
422   count = 1;
423   while (1) {
424     if (lambda <= minlambda) { /* bad luck; use full step */
425       PLogInfo(snes,
426           "SNESQuadraticLineSearch:Unable to find good step length! %d \n",count);
427       PLogInfo(snes,
428       "SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
429           fnorm,*gnorm,*ynorm,lambda,initslope);
430       ierr = VecCopy(w,y); CHKERRQ(ierr);
431       *flag = -1; break;
432     }
433     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
434     lambdaprev = lambda;
435     gnormprev = *gnorm;
436     if (lambdatemp <= .1*lambda) {
437       lambda = .1*lambda;
438     } else lambda = lambdatemp;
439     ierr = VecCopy(x,w); CHKERRQ(ierr);
440     lambda = -lambda;
441 #if defined(PETSC_COMPLEX)
442     clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
443 #else
444     ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr);
445 #endif
446     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
447     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
448     if (*gnorm <= fnorm + alpha*initslope) {      /* sufficient reduction */
449       ierr = VecCopy(w,y); CHKERRQ(ierr);
450       PLogInfo(snes,
451         "SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda);
452       break;
453     }
454     count++;
455   }
456   theend2:
457   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
458   return 0;
459 }
460 /* ------------------------------------------------------------ */
461 #undef __FUNC__
462 #define __FUNC__ "SNESSetLineSearch" /* ADIC Ignore */
463 /*@C
464    SNESSetLineSearch - Sets the line search routine to be used
465    by the method SNES_EQ_LS.
466 
467    Input Parameters:
468 .  snes - nonlinear context obtained from SNESCreate()
469 .  func - pointer to int function
470 
471    Available Routines:
472 .  SNESCubicLineSearch() - default line search
473 .  SNESQuadraticLineSearch() - quadratic line search
474 .  SNESNoLineSearch() - the full Newton step (actually not a line search)
475 
476     Options Database Keys:
477 $   -snes_eq_ls [basic,quadratic,cubic]
478 $   -snes_eq_ls_alpha <alpha>
479 $   -snes_eq_ls_maxstep <max>
480 $   -snes_eq_ls_steptol <steptol>
481 
482    Calling sequence of func:
483    func (SNES snes, Vec x, Vec f, Vec g, Vec y,
484          Vec w, double fnorm, double *ynorm,
485          double *gnorm, *flag)
486 
487     Input parameters for func:
488 .   snes - nonlinear context
489 .   x - current iterate
490 .   f - residual evaluated at x
491 .   y - search direction (contains new iterate on output)
492 .   w - work vector
493 .   fnorm - 2-norm of f
494 
495     Output parameters for func:
496 .   g - residual evaluated at new iterate y
497 .   y - new iterate (contains search direction on input)
498 .   gnorm - 2-norm of g
499 .   ynorm - 2-norm of search length
500 .   flag - set to 0 if the line search succeeds; a nonzero integer
501            on failure.
502 
503 .keywords: SNES, nonlinear, set, line search, routine
504 
505 .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch()
506 @*/
507 int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec,
508                              double,double*,double*,int*))
509 {
510   if ((snes)->type == SNES_EQ_LS) ((SNES_LS *)(snes->data))->LineSearch = func;
511   return 0;
512 }
513 /* ------------------------------------------------------------------ */
514 #undef __FUNC__
515 #define __FUNC__ "SNESPrintHelp_EQ_LS" /* ADIC Ignore */
516 static int SNESPrintHelp_EQ_LS(SNES snes,char *p)
517 {
518   SNES_LS *ls = (SNES_LS *)snes->data;
519 
520   PetscPrintf(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n");
521   PetscPrintf(snes->comm,"   %ssnes_eq_ls [basic,quadratic,cubic]\n",p);
522   PetscPrintf(snes->comm,"   %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha);
523   PetscPrintf(snes->comm,"   %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep);
524   PetscPrintf(snes->comm,"   %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol);
525   return 0;
526 }
527 /* ------------------------------------------------------------------ */
528 #undef __FUNC__
529 #define __FUNC__ "SNESView_EQ_LS" /* ADIC Ignore */
530 static int SNESView_EQ_LS(PetscObject obj,Viewer viewer)
531 {
532   SNES       snes = (SNES)obj;
533   SNES_LS    *ls = (SNES_LS *)snes->data;
534   FILE       *fd;
535   char       *cstr;
536   int        ierr;
537   ViewerType vtype;
538 
539   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
540   if (vtype  == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
541     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
542     if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch";
543     else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch";
544     else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch";
545     else cstr = "unknown";
546     PetscFPrintf(snes->comm,fd,"    line search variant: %s\n",cstr);
547     PetscFPrintf(snes->comm,fd,"    alpha=%g, maxstep=%g, steptol=%g\n",
548                  ls->alpha,ls->maxstep,ls->steptol);
549   }
550   return 0;
551 }
552 /* ------------------------------------------------------------------ */
553 #undef __FUNC__
554 #define __FUNC__ "SNESSetFromOptions_EQ_LS"
555 static int SNESSetFromOptions_EQ_LS(SNES snes)
556 {
557   SNES_LS *ls = (SNES_LS *)snes->data;
558   char    ver[16];
559   double  tmp;
560   int     ierr,flg;
561 
562   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr);
563   if (flg) {
564     ls->alpha = tmp;
565   }
566   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr);
567   if (flg) {
568     ls->maxstep = tmp;
569   }
570   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr);
571   if (flg) {
572     ls->steptol = tmp;
573   }
574   ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr);
575   if (flg) {
576     if (!PetscStrcmp(ver,"basic")) {
577       SNESSetLineSearch(snes,SNESNoLineSearch);
578     }
579     else if (!PetscStrcmp(ver,"quadratic")) {
580       SNESSetLineSearch(snes,SNESQuadraticLineSearch);
581     }
582     else if (!PetscStrcmp(ver,"cubic")) {
583       SNESSetLineSearch(snes,SNESCubicLineSearch);
584     }
585     else {SETERRQ(1,0,"Unknown line search");}
586   }
587   return 0;
588 }
589 /* ------------------------------------------------------------ */
590 #undef __FUNC__
591 #define __FUNC__ "SNESCreate_EQ_LS"
592 int SNESCreate_EQ_LS(SNES  snes )
593 {
594   SNES_LS *neP;
595 
596   if (snes->method_class != SNES_NONLINEAR_EQUATIONS)
597     SETERRQ(1,0,"For SNES_NONLINEAR_EQUATIONS only");
598   snes->type		= SNES_EQ_LS;
599   snes->setup		= SNESSetUp_EQ_LS;
600   snes->solve		= SNESSolve_EQ_LS;
601   snes->destroy		= SNESDestroy_EQ_LS;
602   snes->converged	= SNESConverged_EQ_LS;
603   snes->printhelp       = SNESPrintHelp_EQ_LS;
604   snes->setfromoptions  = SNESSetFromOptions_EQ_LS;
605   snes->view            = SNESView_EQ_LS;
606   snes->nwork           = 0;
607 
608   neP			= PetscNew(SNES_LS);   CHKPTRQ(neP);
609   PLogObjectMemory(snes,sizeof(SNES_LS));
610   snes->data    	= (void *) neP;
611   neP->alpha		= 1.e-4;
612   neP->maxstep		= 1.e8;
613   neP->steptol		= 1.e-12;
614   neP->LineSearch       = SNESCubicLineSearch;
615   return 0;
616 }
617 
618