xref: /petsc/src/snes/impls/ls/ls.c (revision e1311b9049e89cb3452dcd306fde571f4b440ff2)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*e1311b90SBarry Smith static char vcid[] = "$Id: ls.c,v 1.102 1998/03/20 22:52:30 bsmith Exp bsmith $";
35e76c431SBarry Smith #endif
45e76c431SBarry Smith 
55e76c431SBarry Smith #include <math.h>
670f55243SBarry Smith #include "src/snes/impls/ls/ls.h"
7b16a3bb1SBarry Smith #include "pinclude/pviewer.h"
85e42470aSBarry Smith 
95e42470aSBarry Smith /*
105e42470aSBarry Smith      Implements a line search variant of Newton's Method
115e76c431SBarry Smith     for solving systems of nonlinear equations.
125e76c431SBarry Smith 
135e76c431SBarry Smith     Input parameters:
145e42470aSBarry Smith .   snes - nonlinear context obtained from SNESCreate()
155e76c431SBarry Smith 
165e42470aSBarry Smith     Output Parameters:
17a935fc98SLois Curfman McInnes .   outits  - Number of global iterations until termination.
185e76c431SBarry Smith 
195e76c431SBarry Smith     Notes:
205e76c431SBarry Smith     This implements essentially a truncated Newton method with a
215e76c431SBarry Smith     line search.  By default a cubic backtracking line search
225e76c431SBarry Smith     is employed, as described in the text "Numerical Methods for
235e76c431SBarry Smith     Unconstrained Optimization and Nonlinear Equations" by Dennis
24393d2d9aSLois Curfman McInnes     and Schnabel.
255e76c431SBarry Smith */
265e76c431SBarry Smith 
275615d1e5SSatish Balay #undef __FUNC__
285615d1e5SSatish Balay #define __FUNC__ "SNESSolve_EQ_LS"
29f63b844aSLois Curfman McInnes int SNESSolve_EQ_LS(SNES snes,int *outits)
305e76c431SBarry Smith {
315e42470aSBarry Smith   SNES_LS       *neP = (SNES_LS *) snes->data;
32761aaf1bSLois Curfman McInnes   int           maxits, i, history_len, ierr, lits, lsfail;
33112a2221SBarry Smith   MatStructure  flg = DIFFERENT_NONZERO_PATTERN;
346b5873e3SBarry Smith   double        fnorm, gnorm, xnorm, ynorm, *history;
355e42470aSBarry Smith   Vec           Y, X, F, G, W, TMP;
365e76c431SBarry Smith 
373a40ed3dSBarry Smith   PetscFunctionBegin;
385e42470aSBarry Smith   history	= snes->conv_hist;	/* convergence history */
3951979daaSLois Curfman McInnes   history_len	= snes->conv_hist_size;	/* convergence history length */
405e42470aSBarry Smith   maxits	= snes->max_its;	/* maximum number of iterations */
415e42470aSBarry Smith   X		= snes->vec_sol;	/* solution vector */
4239e2f89bSBarry Smith   F		= snes->vec_func;	/* residual vector */
435e42470aSBarry Smith   Y		= snes->work[0];	/* work vectors */
445e42470aSBarry Smith   G		= snes->work[1];
455e42470aSBarry Smith   W		= snes->work[2];
465e76c431SBarry Smith 
4725ed9cd1SBarry Smith   snes->iter = 0;
485334005bSBarry Smith   ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr);  /*  F(X)      */
49cddf8d76SBarry Smith   ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr);	/* fnorm <- ||F||  */
505e42470aSBarry Smith   snes->norm = fnorm;
5151979daaSLois Curfman McInnes   if (history) history[0] = fnorm;
5294a424c1SBarry Smith   SNESMonitor(snes,0,fnorm);
535e76c431SBarry Smith 
543a40ed3dSBarry Smith   if (fnorm < snes->atol) {*outits = 0; PetscFunctionReturn(0);}
5594a9d846SBarry Smith 
56d034289bSBarry Smith   /* set parameter for default relative tolerance convergence test */
57d034289bSBarry Smith   snes->ttol = fnorm*snes->rtol;
58d034289bSBarry Smith 
595e76c431SBarry Smith   for ( i=0; i<maxits; i++ ) {
605e42470aSBarry Smith     snes->iter = i+1;
615e76c431SBarry Smith 
62ea4d3ed3SLois Curfman McInnes     /* Solve J Y = F, where J is Jacobian matrix */
635334005bSBarry Smith     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg); CHKERRQ(ierr);
645334005bSBarry Smith     ierr = SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,flg); CHKERRQ(ierr);
6578b31e54SBarry Smith     ierr = SLESSolve(snes->sles,F,Y,&lits); CHKERRQ(ierr);
667a00f4a9SLois Curfman McInnes     snes->linear_its += PetscAbsInt(lits);
67af1ccdebSLois Curfman McInnes     PLogInfo(snes,"SNESSolve_EQ_LS: iter=%d, linear solve iterations=%d\n",snes->iter,lits);
68ea4d3ed3SLois Curfman McInnes 
69ea4d3ed3SLois Curfman McInnes     /* Compute a (scaled) negative update in the line search routine:
70ea4d3ed3SLois Curfman McInnes          Y <- X - lambda*Y
71ea4d3ed3SLois Curfman McInnes        and evaluate G(Y) = function(Y))
72ea4d3ed3SLois Curfman McInnes     */
7381b6cf68SLois Curfman McInnes     ierr = VecCopy(Y,snes->vec_sol_update_always); CHKERRQ(ierr);
74ddd12767SBarry Smith     ierr = (*neP->LineSearch)(snes,X,F,G,Y,W,fnorm,&ynorm,&gnorm,&lsfail); CHKERRQ(ierr);
75af1ccdebSLois Curfman McInnes     PLogInfo(snes,"SNESSolve_EQ_LS: fnorm=%g, gnorm=%g, ynorm=%g, lsfail=%d\n",fnorm,gnorm,ynorm,lsfail);
76761aaf1bSLois Curfman McInnes     if (lsfail) snes->nfailures++;
775e76c431SBarry Smith 
7839e2f89bSBarry Smith     TMP = F; F = G; snes->vec_func_always = F; G = TMP;
7939e2f89bSBarry Smith     TMP = X; X = Y; snes->vec_sol_always = X;  Y = TMP;
805e76c431SBarry Smith     fnorm = gnorm;
815e76c431SBarry Smith 
825e42470aSBarry Smith     snes->norm = fnorm;
835e76c431SBarry Smith     if (history && history_len > i+1) history[i+1] = fnorm;
8494a424c1SBarry Smith     SNESMonitor(snes,i+1,fnorm);
855e76c431SBarry Smith 
865e76c431SBarry Smith     /* Test for convergence */
8729e0b56fSBarry Smith     if (snes->converged) {
8829e0b56fSBarry Smith       ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr);	/* xnorm = || X || */
89bbb6d6a8SBarry Smith       if ((*snes->converged)(snes,xnorm,ynorm,fnorm,snes->cnvP)) {
9016c95cacSBarry Smith         break;
9116c95cacSBarry Smith       }
9216c95cacSBarry Smith     }
9329e0b56fSBarry Smith   }
9439e2f89bSBarry Smith   if (X != snes->vec_sol) {
95393d2d9aSLois Curfman McInnes     ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr);
9639e2f89bSBarry Smith     snes->vec_sol_always  = snes->vec_sol;
9739e2f89bSBarry Smith     snes->vec_func_always = snes->vec_func;
9839e2f89bSBarry Smith   }
9952392280SLois Curfman McInnes   if (i == maxits) {
100981c4779SBarry Smith     PLogInfo(snes,"SNESSolve_EQ_LS: Maximum number of iterations has been reached: %d\n",maxits);
10152392280SLois Curfman McInnes     i--;
10252392280SLois Curfman McInnes   }
10351979daaSLois Curfman McInnes   if (history) snes->conv_act_size = (history_len < i+1) ? history_len : i+1;
1045e42470aSBarry Smith   *outits = i+1;
1053a40ed3dSBarry Smith   PetscFunctionReturn(0);
1065e76c431SBarry Smith }
1075e76c431SBarry Smith /* ------------------------------------------------------------ */
1085615d1e5SSatish Balay #undef __FUNC__
1095615d1e5SSatish Balay #define __FUNC__ "SNESSetUp_EQ_LS"
110f63b844aSLois Curfman McInnes int SNESSetUp_EQ_LS(SNES snes )
1115e76c431SBarry Smith {
1125e42470aSBarry Smith   int ierr;
1133a40ed3dSBarry Smith 
1143a40ed3dSBarry Smith   PetscFunctionBegin;
11581b6cf68SLois Curfman McInnes   snes->nwork = 4;
116d7e8b826SBarry Smith   ierr = VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);CHKERRQ(ierr);
1175e42470aSBarry Smith   PLogObjectParents(snes,snes->nwork,snes->work);
11881b6cf68SLois Curfman McInnes   snes->vec_sol_update_always = snes->work[3];
1193a40ed3dSBarry Smith   PetscFunctionReturn(0);
1205e76c431SBarry Smith }
1215e76c431SBarry Smith /* ------------------------------------------------------------ */
1225615d1e5SSatish Balay #undef __FUNC__
123d4bb536fSBarry Smith #define __FUNC__ "SNESDestroy_EQ_LS"
124*e1311b90SBarry Smith int SNESDestroy_EQ_LS(SNES snes)
1255e76c431SBarry Smith {
126393d2d9aSLois Curfman McInnes   int  ierr;
1273a40ed3dSBarry Smith 
1283a40ed3dSBarry Smith   PetscFunctionBegin;
1295baf8537SBarry Smith   if (snes->nwork) {
1304b0e389bSBarry Smith     ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr);
13121c89e3eSBarry Smith   }
1320452661fSBarry Smith   PetscFree(snes->data);
1333a40ed3dSBarry Smith   PetscFunctionReturn(0);
1345e76c431SBarry Smith }
1355e76c431SBarry Smith /* ------------------------------------------------------------ */
1365615d1e5SSatish Balay #undef __FUNC__
1375615d1e5SSatish Balay #define __FUNC__ "SNESNoLineSearch"
13882bf6240SBarry Smith 
1394b828684SBarry Smith /*@C
1405e42470aSBarry Smith    SNESNoLineSearch - This routine is not a line search at all;
1415e76c431SBarry Smith    it simply uses the full Newton step.  Thus, this routine is intended
1425e76c431SBarry Smith    to serve as a template and is not recommended for general use.
1435e76c431SBarry Smith 
1445e76c431SBarry Smith    Input Parameters:
1455e42470aSBarry Smith .  snes - nonlinear context
1465e76c431SBarry Smith .  x - current iterate
1475e76c431SBarry Smith .  f - residual evaluated at x
1485e76c431SBarry Smith .  y - search direction (contains new iterate on output)
1495e76c431SBarry Smith .  w - work vector
1505e76c431SBarry Smith .  fnorm - 2-norm of f
1515e76c431SBarry Smith 
152c4a48953SLois Curfman McInnes    Output Parameters:
1535e76c431SBarry Smith .  g - residual evaluated at new iterate y
1545e76c431SBarry Smith .  y - new iterate (contains search direction on input)
1555e76c431SBarry Smith .  gnorm - 2-norm of g
1565e76c431SBarry Smith .  ynorm - 2-norm of search length
157761aaf1bSLois Curfman McInnes .  flag - set to 0, indicating a successful line search
1585e76c431SBarry Smith 
159c4a48953SLois Curfman McInnes    Options Database Key:
16009d61ba7SLois Curfman McInnes $  -snes_eq_ls basic
161c4a48953SLois Curfman McInnes 
16228ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
16328ae5a21SLois Curfman McInnes 
164f59ffdedSLois Curfman McInnes .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
16577c4ece6SBarry Smith           SNESSetLineSearch()
1665e76c431SBarry Smith @*/
1675e42470aSBarry Smith int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
168761aaf1bSLois Curfman McInnes                      double fnorm, double *ynorm, double *gnorm,int *flag )
1695e76c431SBarry Smith {
1705e42470aSBarry Smith   int    ierr;
1715334005bSBarry Smith   Scalar mone = -1.0;
1725334005bSBarry Smith 
1733a40ed3dSBarry Smith   PetscFunctionBegin;
174761aaf1bSLois Curfman McInnes   *flag = 0;
1757857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
176cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);       /* ynorm = || y || */
177ea4d3ed3SLois Curfman McInnes   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
178ea4d3ed3SLois Curfman McInnes   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
179cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);       /* gnorm = || g || */
1807857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
1813a40ed3dSBarry Smith   PetscFunctionReturn(0);
1825e76c431SBarry Smith }
1835e76c431SBarry Smith /* ------------------------------------------------------------------ */
1845615d1e5SSatish Balay #undef __FUNC__
18529e0b56fSBarry Smith #define __FUNC__ "SNESNoLineSearchNoNorms"
18682bf6240SBarry Smith 
18729e0b56fSBarry Smith /*@C
18829e0b56fSBarry Smith    SNESNoLineSearchNoNorms - This routine is not a line search at
18929e0b56fSBarry Smith    all; it simply uses the full Newton step. This version does not
19029e0b56fSBarry Smith    even compute the norm of the function or search direction; this
19129e0b56fSBarry Smith    is intended only when you know the full step is fine and are
19229e0b56fSBarry Smith    not checking for convergence of the nonlinear iteration (for
19329e0b56fSBarry Smith    example, you are running always for a fixed number of Newton
19429e0b56fSBarry Smith    steps).
19529e0b56fSBarry Smith 
19629e0b56fSBarry Smith    Input Parameters:
19729e0b56fSBarry Smith .  snes - nonlinear context
19829e0b56fSBarry Smith .  x - current iterate
19929e0b56fSBarry Smith .  f - residual evaluated at x
20029e0b56fSBarry Smith .  y - search direction (contains new iterate on output)
20129e0b56fSBarry Smith .  w - work vector
20229e0b56fSBarry Smith .  fnorm - 2-norm of f
20329e0b56fSBarry Smith 
20429e0b56fSBarry Smith    Output Parameters:
20529e0b56fSBarry Smith .  g - residual evaluated at new iterate y
20629e0b56fSBarry Smith .  gnorm - not changed
20729e0b56fSBarry Smith .  ynorm - not changed
20829e0b56fSBarry Smith .  flag - set to 0, indicating a successful line search
20929e0b56fSBarry Smith 
21029e0b56fSBarry Smith    Options Database Key:
21129e0b56fSBarry Smith $  -snes_eq_ls basicnonorms
21229e0b56fSBarry Smith 
21329e0b56fSBarry Smith .keywords: SNES, nonlinear, line search, cubic
21429e0b56fSBarry Smith 
21529e0b56fSBarry Smith .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
21629e0b56fSBarry Smith           SNESSetLineSearch(), SNESNoLineSearch()
21729e0b56fSBarry Smith @*/
21829e0b56fSBarry Smith int SNESNoLineSearchNoNorms(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
21929e0b56fSBarry Smith                      double fnorm, double *ynorm, double *gnorm,int *flag )
22029e0b56fSBarry Smith {
22129e0b56fSBarry Smith   int    ierr;
22229e0b56fSBarry Smith   Scalar mone = -1.0;
22329e0b56fSBarry Smith 
2243a40ed3dSBarry Smith   PetscFunctionBegin;
22529e0b56fSBarry Smith   *flag = 0;
22629e0b56fSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
22729e0b56fSBarry Smith   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
22829e0b56fSBarry Smith   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
22929e0b56fSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
2303a40ed3dSBarry Smith   PetscFunctionReturn(0);
23129e0b56fSBarry Smith }
23229e0b56fSBarry Smith /* ------------------------------------------------------------------ */
23329e0b56fSBarry Smith #undef __FUNC__
2345615d1e5SSatish Balay #define __FUNC__ "SNESCubicLineSearch"
2354b828684SBarry Smith /*@C
236f525115eSLois Curfman McInnes    SNESCubicLineSearch - Performs a cubic line search (default line search method).
2375e76c431SBarry Smith 
2385e76c431SBarry Smith    Input Parameters:
2395e42470aSBarry Smith .  snes - nonlinear context
2405e76c431SBarry Smith .  x - current iterate
2415e76c431SBarry Smith .  f - residual evaluated at x
2425e76c431SBarry Smith .  y - search direction (contains new iterate on output)
2435e76c431SBarry Smith .  w - work vector
2445e76c431SBarry Smith .  fnorm - 2-norm of f
2455e76c431SBarry Smith 
246393d2d9aSLois Curfman McInnes    Output Parameters:
2475e76c431SBarry Smith .  g - residual evaluated at new iterate y
2485e76c431SBarry Smith .  y - new iterate (contains search direction on input)
2495e76c431SBarry Smith .  gnorm - 2-norm of g
2505e76c431SBarry Smith .  ynorm - 2-norm of search length
251761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
2525e76c431SBarry Smith 
253c4a48953SLois Curfman McInnes    Options Database Key:
25409d61ba7SLois Curfman McInnes $  -snes_eq_ls cubic
255c4a48953SLois Curfman McInnes 
2565e76c431SBarry Smith    Notes:
2575e76c431SBarry Smith    This line search is taken from "Numerical Methods for Unconstrained
2585e76c431SBarry Smith    Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325.
2595e76c431SBarry Smith 
26028ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
26128ae5a21SLois Curfman McInnes 
26277c4ece6SBarry Smith .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
2635e76c431SBarry Smith @*/
2645e42470aSBarry Smith int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w,
265761aaf1bSLois Curfman McInnes                         double fnorm,double *ynorm,double *gnorm,int *flag)
2665e76c431SBarry Smith {
267406556e6SLois Curfman McInnes   /*
268406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
269406556e6SLois Curfman McInnes      minimization problem:
270406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
271406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
272406556e6SLois Curfman McInnes    */
273406556e6SLois Curfman McInnes 
274ddd12767SBarry Smith   double  steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2;
275ea4d3ed3SLois Curfman McInnes   double  maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg;
2763a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
2775e42470aSBarry Smith   Scalar  cinitslope, clambda;
2786b5873e3SBarry Smith #endif
2795e42470aSBarry Smith   int     ierr, count;
2805e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
2815334005bSBarry Smith   Scalar  mone = -1.0,scale;
2825e76c431SBarry Smith 
2833a40ed3dSBarry Smith   PetscFunctionBegin;
2847857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
285761aaf1bSLois Curfman McInnes   *flag   = 0;
2865e76c431SBarry Smith   alpha   = neP->alpha;
2875e76c431SBarry Smith   maxstep = neP->maxstep;
2885e76c431SBarry Smith   steptol = neP->steptol;
2895e76c431SBarry Smith 
290cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);
291a1c2b6eeSLois Curfman McInnes   if (*ynorm < snes->atol) {
292a1c2b6eeSLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Search direction and size are nearly 0\n");
293a1c2b6eeSLois Curfman McInnes     *gnorm = fnorm;
294a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
295a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
296ad922ac9SBarry Smith     goto theend1;
29794a9d846SBarry Smith   }
2985e76c431SBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
2995e42470aSBarry Smith     scale = maxstep/(*ynorm);
3003a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
30194a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale));
3026b5873e3SBarry Smith #else
30394a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale);
3046b5873e3SBarry Smith #endif
305393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
3065e76c431SBarry Smith     *ynorm = maxstep;
3075e76c431SBarry Smith   }
3085e76c431SBarry Smith   minlambda = steptol/(*ynorm);
309a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
3103a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
311a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
3125e42470aSBarry Smith   initslope = real(cinitslope);
3135e42470aSBarry Smith #else
314a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
3155e42470aSBarry Smith #endif
3165e76c431SBarry Smith   if (initslope > 0.0) initslope = -initslope;
3175e76c431SBarry Smith   if (initslope == 0.0) initslope = -1.0;
3185e76c431SBarry Smith 
319393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
3205334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
32178b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
322cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm);
323406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
324393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
32594a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Using full step\n");
326ad922ac9SBarry Smith     goto theend1;
3275e76c431SBarry Smith   }
3285e76c431SBarry Smith 
3295e76c431SBarry Smith   /* Fit points with quadratic */
3305e76c431SBarry Smith   lambda = 1.0; count = 0;
331a703fe33SLois Curfman McInnes   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
3325e76c431SBarry Smith   lambdaprev = lambda;
3335e76c431SBarry Smith   gnormprev = *gnorm;
334ddd12767SBarry Smith   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
335ddd12767SBarry Smith   else lambda = lambdatemp;
336393d2d9aSLois Curfman McInnes   ierr   = VecCopy(x,w); CHKERRQ(ierr);
337ea4d3ed3SLois Curfman McInnes   lambdaneg = -lambda;
3383a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
339ea4d3ed3SLois Curfman McInnes   clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3405e42470aSBarry Smith #else
341ea4d3ed3SLois Curfman McInnes   ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3425e42470aSBarry Smith #endif
34378b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
344cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
345406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
346393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
347ea4d3ed3SLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda);
348ad922ac9SBarry Smith     goto theend1;
3495e76c431SBarry Smith   }
3505e76c431SBarry Smith 
3515e76c431SBarry Smith   /* Fit points with cubic */
3525e76c431SBarry Smith   count = 1;
3535e76c431SBarry Smith   while (1) {
3545e76c431SBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
3552b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:Unable to find good step length! %d \n",count);
3562b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
357ea4d3ed3SLois Curfman McInnes                fnorm,*gnorm,*ynorm,lambda,initslope);
358393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
359761aaf1bSLois Curfman McInnes       *flag = -1; break;
3605e76c431SBarry Smith     }
361406556e6SLois Curfman McInnes     t1 = ((*gnorm)*(*gnorm) - fnorm*fnorm)*0.5 - lambda*initslope;
362406556e6SLois Curfman McInnes     t2 = (gnormprev*gnormprev  - fnorm*fnorm)*0.5 - lambdaprev*initslope;
363ddd12767SBarry Smith     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3642b022350SLois Curfman McInnes     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3655e76c431SBarry Smith     d  = b*b - 3*a*initslope;
3665e76c431SBarry Smith     if (d < 0.0) d = 0.0;
3675e76c431SBarry Smith     if (a == 0.0) {
3685e76c431SBarry Smith       lambdatemp = -initslope/(2.0*b);
3695e76c431SBarry Smith     } else {
3705e76c431SBarry Smith       lambdatemp = (-b + sqrt(d))/(3.0*a);
3715e76c431SBarry Smith     }
3725e76c431SBarry Smith     if (lambdatemp > .5*lambda) {
3735e76c431SBarry Smith       lambdatemp = .5*lambda;
3745e76c431SBarry Smith     }
3755e76c431SBarry Smith     lambdaprev = lambda;
3765e76c431SBarry Smith     gnormprev = *gnorm;
3775e76c431SBarry Smith     if (lambdatemp <= .1*lambda) {
3785e76c431SBarry Smith       lambda = .1*lambda;
3795e76c431SBarry Smith     }
3805e76c431SBarry Smith     else lambda = lambdatemp;
381393d2d9aSLois Curfman McInnes     ierr = VecCopy( x, w ); CHKERRQ(ierr);
382ea4d3ed3SLois Curfman McInnes     lambdaneg = -lambda;
3833a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
384ea4d3ed3SLois Curfman McInnes     clambda = lambdaneg;
385393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3865e42470aSBarry Smith #else
387ea4d3ed3SLois Curfman McInnes     ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3885e42470aSBarry Smith #endif
38978b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
390cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
391406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* is reduction enough? */
392393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
393ea4d3ed3SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda);
3942715565aSLois Curfman McInnes       goto theend1;
3952b022350SLois Curfman McInnes     } else {
3962b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubic step no good, shrinking lambda,  lambda=%g\n",lambda);
3975e76c431SBarry Smith     }
3985e76c431SBarry Smith     count++;
3995e76c431SBarry Smith   }
400ad922ac9SBarry Smith   theend1:
4017857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
4023a40ed3dSBarry Smith   PetscFunctionReturn(0);
4035e76c431SBarry Smith }
40452392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
4055615d1e5SSatish Balay #undef __FUNC__
4065615d1e5SSatish Balay #define __FUNC__ "SNESQuadraticLineSearch"
4074b828684SBarry Smith /*@C
408f525115eSLois Curfman McInnes    SNESQuadraticLineSearch - Performs a quadratic line search.
4095e76c431SBarry Smith 
4105e42470aSBarry Smith    Input Parameters:
411f59ffdedSLois Curfman McInnes .  snes - the SNES context
4125e42470aSBarry Smith .  x - current iterate
4135e42470aSBarry Smith .  f - residual evaluated at x
4145e42470aSBarry Smith .  y - search direction (contains new iterate on output)
4155e42470aSBarry Smith .  w - work vector
4165e42470aSBarry Smith .  fnorm - 2-norm of f
4175e42470aSBarry Smith 
418c4a48953SLois Curfman McInnes    Output Parameters:
4195e42470aSBarry Smith .  g - residual evaluated at new iterate y
4205e42470aSBarry Smith .  y - new iterate (contains search direction on input)
4215e42470aSBarry Smith .  gnorm - 2-norm of g
4225e42470aSBarry Smith .  ynorm - 2-norm of search length
423761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
4245e42470aSBarry Smith 
425c4a48953SLois Curfman McInnes    Options Database Key:
42609d61ba7SLois Curfman McInnes $  -snes_eq_ls quadratic
427c4a48953SLois Curfman McInnes 
4285e42470aSBarry Smith    Notes:
42977c4ece6SBarry Smith    Use SNESSetLineSearch()
430f63b844aSLois Curfman McInnes    to set this routine within the SNES_EQ_LS method.
4315e42470aSBarry Smith 
432f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, quadratic, line search
433f59ffdedSLois Curfman McInnes 
43477c4ece6SBarry Smith .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
4355e42470aSBarry Smith @*/
4365e42470aSBarry Smith int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
437761aaf1bSLois Curfman McInnes                            double fnorm, double *ynorm, double *gnorm,int *flag)
4385e76c431SBarry Smith {
439406556e6SLois Curfman McInnes   /*
440406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
441406556e6SLois Curfman McInnes      minimization problem:
442406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
443406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
444406556e6SLois Curfman McInnes    */
44540011551SBarry Smith   double  steptol,initslope,maxstep,minlambda,alpha,lambda,lambdatemp;
4463a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
4475e42470aSBarry Smith   Scalar  cinitslope,clambda;
4486b5873e3SBarry Smith #endif
4495e42470aSBarry Smith   int     ierr,count;
4505e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
4515334005bSBarry Smith   Scalar  mone = -1.0,scale;
4525e76c431SBarry Smith 
4533a40ed3dSBarry Smith   PetscFunctionBegin;
4547857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
455761aaf1bSLois Curfman McInnes   *flag   = 0;
4565e42470aSBarry Smith   alpha   = neP->alpha;
4575e42470aSBarry Smith   maxstep = neP->maxstep;
4585e42470aSBarry Smith   steptol = neP->steptol;
4595e76c431SBarry Smith 
460cddf8d76SBarry Smith   VecNorm(y, NORM_2,ynorm );
461b37302c6SLois Curfman McInnes   if (*ynorm < snes->atol) {
46294a9d846SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n");
463b37302c6SLois Curfman McInnes     *gnorm = fnorm;
464b37302c6SLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
465b37302c6SLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
466ad922ac9SBarry Smith     goto theend2;
46794a9d846SBarry Smith   }
4685e42470aSBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
4695e42470aSBarry Smith     scale = maxstep/(*ynorm);
470393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
4715e42470aSBarry Smith     *ynorm = maxstep;
4725e76c431SBarry Smith   }
4735e42470aSBarry Smith   minlambda = steptol/(*ynorm);
474a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
4753a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
476a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
4775e42470aSBarry Smith   initslope = real(cinitslope);
4785e42470aSBarry Smith #else
479a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
4805e42470aSBarry Smith #endif
4815e42470aSBarry Smith   if (initslope > 0.0) initslope = -initslope;
4825e42470aSBarry Smith   if (initslope == 0.0) initslope = -1.0;
4835e42470aSBarry Smith 
484393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
4855334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
48678b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
487cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
488406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
489393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
49094a424c1SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n");
491ad922ac9SBarry Smith     goto theend2;
4925e42470aSBarry Smith   }
4935e42470aSBarry Smith 
4945e42470aSBarry Smith   /* Fit points with quadratic */
4955e42470aSBarry Smith   lambda = 1.0; count = 0;
4965e42470aSBarry Smith   count = 1;
4975e42470aSBarry Smith   while (1) {
4985e42470aSBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
499981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:Unable to find good step length! %d \n",count);
500981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
501ea4d3ed3SLois Curfman McInnes                fnorm,*gnorm,*ynorm,lambda,initslope);
502393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
503761aaf1bSLois Curfman McInnes       *flag = -1; break;
5045e42470aSBarry Smith     }
505a703fe33SLois Curfman McInnes     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
5065e42470aSBarry Smith     if (lambdatemp <= .1*lambda) {
5075e42470aSBarry Smith       lambda = .1*lambda;
5085e42470aSBarry Smith     } else lambda = lambdatemp;
509393d2d9aSLois Curfman McInnes     ierr = VecCopy(x,w); CHKERRQ(ierr);
5105334005bSBarry Smith     lambda = -lambda;
5113a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
512393d2d9aSLois Curfman McInnes     clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
5135e42470aSBarry Smith #else
514393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr);
5155e42470aSBarry Smith #endif
51678b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
517cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
518406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
519393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
520981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda);
52106259719SBarry Smith       break;
5225e42470aSBarry Smith     }
5235e42470aSBarry Smith     count++;
5245e42470aSBarry Smith   }
525ad922ac9SBarry Smith   theend2:
5267857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
5273a40ed3dSBarry Smith   PetscFunctionReturn(0);
5285e76c431SBarry Smith }
52982bf6240SBarry Smith 
5305e76c431SBarry Smith /* ------------------------------------------------------------ */
5315615d1e5SSatish Balay #undef __FUNC__
532d4bb536fSBarry Smith #define __FUNC__ "SNESSetLineSearch"
533c9e6a524SLois Curfman McInnes /*@C
53477c4ece6SBarry Smith    SNESSetLineSearch - Sets the line search routine to be used
535f63b844aSLois Curfman McInnes    by the method SNES_EQ_LS.
5365e76c431SBarry Smith 
5375e76c431SBarry Smith    Input Parameters:
538eafb4bcbSBarry Smith .  snes - nonlinear context obtained from SNESCreate()
5395e76c431SBarry Smith .  func - pointer to int function
5405e76c431SBarry Smith 
541c4a48953SLois Curfman McInnes    Available Routines:
542f59ffdedSLois Curfman McInnes .  SNESCubicLineSearch() - default line search
543f59ffdedSLois Curfman McInnes .  SNESQuadraticLineSearch() - quadratic line search
544f59ffdedSLois Curfman McInnes .  SNESNoLineSearch() - the full Newton step (actually not a line search)
54582bf6240SBarry Smith .  SNESNoLineSearchNoNorms() - use the full Newton step (calculate no norms; faster in parallel)
5465e76c431SBarry Smith 
547c4a48953SLois Curfman McInnes     Options Database Keys:
54809d61ba7SLois Curfman McInnes $   -snes_eq_ls [basic,quadratic,cubic]
549912ebf9aSLois Curfman McInnes $   -snes_eq_ls_alpha <alpha>
550912ebf9aSLois Curfman McInnes $   -snes_eq_ls_maxstep <max>
551912ebf9aSLois Curfman McInnes $   -snes_eq_ls_steptol <steptol>
552c4a48953SLois Curfman McInnes 
5535e76c431SBarry Smith    Calling sequence of func:
554f59ffdedSLois Curfman McInnes    func (SNES snes, Vec x, Vec f, Vec g, Vec y,
555761aaf1bSLois Curfman McInnes          Vec w, double fnorm, double *ynorm,
556761aaf1bSLois Curfman McInnes          double *gnorm, *flag)
5575e76c431SBarry Smith 
5585e76c431SBarry Smith     Input parameters for func:
5595e42470aSBarry Smith .   snes - nonlinear context
5605e76c431SBarry Smith .   x - current iterate
5615e76c431SBarry Smith .   f - residual evaluated at x
5625e76c431SBarry Smith .   y - search direction (contains new iterate on output)
5635e76c431SBarry Smith .   w - work vector
5645e76c431SBarry Smith .   fnorm - 2-norm of f
5655e76c431SBarry Smith 
5665e76c431SBarry Smith     Output parameters for func:
5675e76c431SBarry Smith .   g - residual evaluated at new iterate y
5685e76c431SBarry Smith .   y - new iterate (contains search direction on input)
5695e76c431SBarry Smith .   gnorm - 2-norm of g
5705e76c431SBarry Smith .   ynorm - 2-norm of search length
571761aaf1bSLois Curfman McInnes .   flag - set to 0 if the line search succeeds; a nonzero integer
572761aaf1bSLois Curfman McInnes            on failure.
573f59ffdedSLois Curfman McInnes 
574f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, set, line search, routine
575f59ffdedSLois Curfman McInnes 
576f59ffdedSLois Curfman McInnes .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch()
5775e76c431SBarry Smith @*/
57877c4ece6SBarry Smith int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec,
579761aaf1bSLois Curfman McInnes                              double,double*,double*,int*))
5805e76c431SBarry Smith {
58182bf6240SBarry Smith   int ierr, (*f)(SNES,int (*f)(SNES,Vec,Vec,Vec,Vec,Vec,double,double*,double*,int*));
58282bf6240SBarry Smith 
5833a40ed3dSBarry Smith   PetscFunctionBegin;
584*e1311b90SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESSetLineSearch",(void **)&f);CHKERRQ(ierr);
58582bf6240SBarry Smith   if (f) {
58682bf6240SBarry Smith     ierr = (*f)(snes,func);CHKERRQ(ierr);
58782bf6240SBarry Smith   }
5883a40ed3dSBarry Smith   PetscFunctionReturn(0);
5895e76c431SBarry Smith }
59082bf6240SBarry Smith 
59182bf6240SBarry Smith #undef __FUNC__
59282bf6240SBarry Smith #define __FUNC__ "SNESSetLineSearch_LS"
59382bf6240SBarry Smith int SNESSetLineSearch_LS(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec,
59482bf6240SBarry Smith                          double,double*,double*,int*))
59582bf6240SBarry Smith {
59682bf6240SBarry Smith   PetscFunctionBegin;
59782bf6240SBarry Smith   ((SNES_LS *)(snes->data))->LineSearch = func;
59882bf6240SBarry Smith   PetscFunctionReturn(0);
59982bf6240SBarry Smith }
60082bf6240SBarry Smith 
60152392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6025615d1e5SSatish Balay #undef __FUNC__
603d4bb536fSBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS"
604f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p)
6055e42470aSBarry Smith {
6065e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
6076daaf66cSBarry Smith 
6083a40ed3dSBarry Smith   PetscFunctionBegin;
60976be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n");
61076be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls [basic,quadratic,cubic]\n",p);
61176be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha);
61276be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep);
61376be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol);
6143a40ed3dSBarry Smith   PetscFunctionReturn(0);
6155e42470aSBarry Smith }
61652392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6175615d1e5SSatish Balay #undef __FUNC__
618d4bb536fSBarry Smith #define __FUNC__ "SNESView_EQ_LS"
619*e1311b90SBarry Smith static int SNESView_EQ_LS(SNES snes,Viewer viewer)
620a935fc98SLois Curfman McInnes {
621a935fc98SLois Curfman McInnes   SNES_LS    *ls = (SNES_LS *)snes->data;
622d636dbe3SBarry Smith   FILE       *fd;
62319bcc07fSBarry Smith   char       *cstr;
62451695f54SLois Curfman McInnes   int        ierr;
62519bcc07fSBarry Smith   ViewerType vtype;
626a935fc98SLois Curfman McInnes 
6273a40ed3dSBarry Smith   PetscFunctionBegin;
62819bcc07fSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
62919bcc07fSBarry Smith   if (vtype  == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
63090ace30eSBarry Smith     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
63119bcc07fSBarry Smith     if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch";
63219bcc07fSBarry Smith     else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch";
63319bcc07fSBarry Smith     else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch";
63419bcc07fSBarry Smith     else cstr = "unknown";
63577c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    line search variant: %s\n",cstr);
63677c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    alpha=%g, maxstep=%g, steptol=%g\n",
637a935fc98SLois Curfman McInnes                  ls->alpha,ls->maxstep,ls->steptol);
63819bcc07fSBarry Smith   }
6393a40ed3dSBarry Smith   PetscFunctionReturn(0);
640a935fc98SLois Curfman McInnes }
64152392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6425615d1e5SSatish Balay #undef __FUNC__
6435615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS"
644f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes)
6455e42470aSBarry Smith {
6465e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
6475e42470aSBarry Smith   char    ver[16];
6485e42470aSBarry Smith   double  tmp;
64925cdf11fSBarry Smith   int     ierr,flg;
6505e42470aSBarry Smith 
6513a40ed3dSBarry Smith   PetscFunctionBegin;
65209d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr);
65325cdf11fSBarry Smith   if (flg) {
6545e42470aSBarry Smith     ls->alpha = tmp;
6555e42470aSBarry Smith   }
65609d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr);
65725cdf11fSBarry Smith   if (flg) {
6585e42470aSBarry Smith     ls->maxstep = tmp;
6595e42470aSBarry Smith   }
66009d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr);
66125cdf11fSBarry Smith   if (flg) {
6625e42470aSBarry Smith     ls->steptol = tmp;
6635e42470aSBarry Smith   }
66409d61ba7SLois Curfman McInnes   ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr);
66525cdf11fSBarry Smith   if (flg) {
66648d91487SBarry Smith     if (!PetscStrcmp(ver,"basic")) {
66777c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearch);
6685e42470aSBarry Smith     }
66929e0b56fSBarry Smith     else if (!PetscStrcmp(ver,"basicnonorms")) {
67029e0b56fSBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearchNoNorms);
67129e0b56fSBarry Smith     }
67248d91487SBarry Smith     else if (!PetscStrcmp(ver,"quadratic")) {
67377c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESQuadraticLineSearch);
6745e42470aSBarry Smith     }
67548d91487SBarry Smith     else if (!PetscStrcmp(ver,"cubic")) {
67677c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESCubicLineSearch);
6775e42470aSBarry Smith     }
678a8c6a408SBarry Smith     else {SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown line search");}
6795e42470aSBarry Smith   }
6803a40ed3dSBarry Smith   PetscFunctionReturn(0);
6815e42470aSBarry Smith }
6825e42470aSBarry Smith /* ------------------------------------------------------------ */
6835615d1e5SSatish Balay #undef __FUNC__
6845615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS"
685f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES  snes )
6865e42470aSBarry Smith {
68782bf6240SBarry Smith   int     ierr;
6885e42470aSBarry Smith   SNES_LS *neP;
6895e42470aSBarry Smith 
6903a40ed3dSBarry Smith   PetscFunctionBegin;
691a8c6a408SBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
692a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only");
693a8c6a408SBarry Smith   }
69482bf6240SBarry Smith 
695f63b844aSLois Curfman McInnes   snes->setup		= SNESSetUp_EQ_LS;
696f63b844aSLois Curfman McInnes   snes->solve		= SNESSolve_EQ_LS;
697f63b844aSLois Curfman McInnes   snes->destroy		= SNESDestroy_EQ_LS;
698f63b844aSLois Curfman McInnes   snes->converged	= SNESConverged_EQ_LS;
699f63b844aSLois Curfman McInnes   snes->printhelp       = SNESPrintHelp_EQ_LS;
700f63b844aSLois Curfman McInnes   snes->setfromoptions  = SNESSetFromOptions_EQ_LS;
701f63b844aSLois Curfman McInnes   snes->view            = SNESView_EQ_LS;
7025baf8537SBarry Smith   snes->nwork           = 0;
7035e42470aSBarry Smith 
7040452661fSBarry Smith   neP			= PetscNew(SNES_LS);   CHKPTRQ(neP);
705ff782a9fSLois Curfman McInnes   PLogObjectMemory(snes,sizeof(SNES_LS));
7065e42470aSBarry Smith   snes->data    	= (void *) neP;
7075e42470aSBarry Smith   neP->alpha		= 1.e-4;
7085e42470aSBarry Smith   neP->maxstep		= 1.e8;
7095e42470aSBarry Smith   neP->steptol		= 1.e-12;
7105e42470aSBarry Smith   neP->LineSearch       = SNESCubicLineSearch;
71182bf6240SBarry Smith 
712*e1311b90SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESSetLineSearch","SNESSetLineSearch_LS",
713*e1311b90SBarry Smith                     (void*)SNESSetLineSearch_LS);CHKERRQ(ierr);
71482bf6240SBarry Smith 
7153a40ed3dSBarry Smith   PetscFunctionReturn(0);
7165e42470aSBarry Smith }
7175e42470aSBarry Smith 
71882bf6240SBarry Smith 
71982bf6240SBarry Smith 
72082bf6240SBarry Smith 
721