xref: /petsc/src/snes/impls/ls/ls.c (revision d4bb536f0e426e9a0292bbfd5743770a9b03f0d5)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*d4bb536fSBarry Smith static char vcid[] = "$Id: ls.c,v 1.94 1997/08/03 16:36:19 curfman 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 
375e42470aSBarry Smith   history	= snes->conv_hist;	/* convergence history */
3851979daaSLois Curfman McInnes   history_len	= snes->conv_hist_size;	/* convergence history length */
395e42470aSBarry Smith   maxits	= snes->max_its;	/* maximum number of iterations */
405e42470aSBarry Smith   X		= snes->vec_sol;	/* solution vector */
4139e2f89bSBarry Smith   F		= snes->vec_func;	/* residual vector */
425e42470aSBarry Smith   Y		= snes->work[0];	/* work vectors */
435e42470aSBarry Smith   G		= snes->work[1];
445e42470aSBarry Smith   W		= snes->work[2];
455e76c431SBarry Smith 
4625ed9cd1SBarry Smith   snes->iter = 0;
475334005bSBarry Smith   ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr);  /*  F(X)      */
48cddf8d76SBarry Smith   ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr);	/* fnorm <- ||F||  */
495e42470aSBarry Smith   snes->norm = fnorm;
5051979daaSLois Curfman McInnes   if (history) history[0] = fnorm;
5194a424c1SBarry Smith   SNESMonitor(snes,0,fnorm);
525e76c431SBarry Smith 
53a1c2b6eeSLois Curfman McInnes   if (fnorm < snes->atol) {*outits = 0; return 0;}
5494a9d846SBarry Smith 
55d034289bSBarry Smith   /* set parameter for default relative tolerance convergence test */
56d034289bSBarry Smith   snes->ttol = fnorm*snes->rtol;
57d034289bSBarry Smith 
585e76c431SBarry Smith   for ( i=0; i<maxits; i++ ) {
595e42470aSBarry Smith     snes->iter = i+1;
605e76c431SBarry Smith 
61ea4d3ed3SLois Curfman McInnes     /* Solve J Y = F, where J is Jacobian matrix */
625334005bSBarry Smith     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg); CHKERRQ(ierr);
635334005bSBarry Smith     ierr = SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,flg); CHKERRQ(ierr);
6478b31e54SBarry Smith     ierr = SLESSolve(snes->sles,F,Y,&lits); CHKERRQ(ierr);
657a00f4a9SLois Curfman McInnes     snes->linear_its += PetscAbsInt(lits);
66af1ccdebSLois Curfman McInnes     PLogInfo(snes,"SNESSolve_EQ_LS: iter=%d, linear solve iterations=%d\n",snes->iter,lits);
67ea4d3ed3SLois Curfman McInnes 
68ea4d3ed3SLois Curfman McInnes     /* Compute a (scaled) negative update in the line search routine:
69ea4d3ed3SLois Curfman McInnes          Y <- X - lambda*Y
70ea4d3ed3SLois Curfman McInnes        and evaluate G(Y) = function(Y))
71ea4d3ed3SLois Curfman McInnes     */
7281b6cf68SLois Curfman McInnes     ierr = VecCopy(Y,snes->vec_sol_update_always); CHKERRQ(ierr);
73ddd12767SBarry Smith     ierr = (*neP->LineSearch)(snes,X,F,G,Y,W,fnorm,&ynorm,&gnorm,&lsfail); CHKERRQ(ierr);
74af1ccdebSLois Curfman McInnes     PLogInfo(snes,"SNESSolve_EQ_LS: fnorm=%g, gnorm=%g, ynorm=%g, lsfail=%d\n",fnorm,gnorm,ynorm,lsfail);
75761aaf1bSLois Curfman McInnes     if (lsfail) snes->nfailures++;
765e76c431SBarry Smith 
7739e2f89bSBarry Smith     TMP = F; F = G; snes->vec_func_always = F; G = TMP;
7839e2f89bSBarry Smith     TMP = X; X = Y; snes->vec_sol_always = X;  Y = TMP;
795e76c431SBarry Smith     fnorm = gnorm;
805e76c431SBarry Smith 
815e42470aSBarry Smith     snes->norm = fnorm;
825e76c431SBarry Smith     if (history && history_len > i+1) history[i+1] = fnorm;
8394a424c1SBarry Smith     SNESMonitor(snes,i+1,fnorm);
845e76c431SBarry Smith 
855e76c431SBarry Smith     /* Test for convergence */
8629e0b56fSBarry Smith     if (snes->converged) {
8729e0b56fSBarry Smith       ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr);	/* xnorm = || X || */
88bbb6d6a8SBarry Smith       if ((*snes->converged)(snes,xnorm,ynorm,fnorm,snes->cnvP)) {
8916c95cacSBarry Smith         break;
9016c95cacSBarry Smith       }
9116c95cacSBarry Smith     }
9229e0b56fSBarry Smith   }
9339e2f89bSBarry Smith   if (X != snes->vec_sol) {
94393d2d9aSLois Curfman McInnes     ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr);
9539e2f89bSBarry Smith     snes->vec_sol_always  = snes->vec_sol;
9639e2f89bSBarry Smith     snes->vec_func_always = snes->vec_func;
9739e2f89bSBarry Smith   }
9852392280SLois Curfman McInnes   if (i == maxits) {
9994a424c1SBarry Smith     PLogInfo(snes,
100f63b844aSLois Curfman McInnes       "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;
1055e42470aSBarry Smith   return 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;
11381b6cf68SLois Curfman McInnes   snes->nwork = 4;
114d7e8b826SBarry Smith   ierr = VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);CHKERRQ(ierr);
1155e42470aSBarry Smith   PLogObjectParents(snes,snes->nwork,snes->work);
11681b6cf68SLois Curfman McInnes   snes->vec_sol_update_always = snes->work[3];
1175e42470aSBarry Smith   return 0;
1185e76c431SBarry Smith }
1195e76c431SBarry Smith /* ------------------------------------------------------------ */
1205615d1e5SSatish Balay #undef __FUNC__
121*d4bb536fSBarry Smith #define __FUNC__ "SNESDestroy_EQ_LS"
122f63b844aSLois Curfman McInnes int SNESDestroy_EQ_LS(PetscObject obj)
1235e76c431SBarry Smith {
1245e42470aSBarry Smith   SNES snes = (SNES) obj;
125393d2d9aSLois Curfman McInnes   int  ierr;
1265baf8537SBarry Smith   if (snes->nwork) {
1274b0e389bSBarry Smith     ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr);
12821c89e3eSBarry Smith   }
1290452661fSBarry Smith   PetscFree(snes->data);
1305e42470aSBarry Smith   return 0;
1315e76c431SBarry Smith }
1325e76c431SBarry Smith /* ------------------------------------------------------------ */
1335615d1e5SSatish Balay #undef __FUNC__
1345615d1e5SSatish Balay #define __FUNC__ "SNESNoLineSearch"
1355e76c431SBarry Smith /*ARGSUSED*/
1364b828684SBarry Smith /*@C
1375e42470aSBarry Smith    SNESNoLineSearch - This routine is not a line search at all;
1385e76c431SBarry Smith    it simply uses the full Newton step.  Thus, this routine is intended
1395e76c431SBarry Smith    to serve as a template and is not recommended for general use.
1405e76c431SBarry Smith 
1415e76c431SBarry Smith    Input Parameters:
1425e42470aSBarry Smith .  snes - nonlinear context
1435e76c431SBarry Smith .  x - current iterate
1445e76c431SBarry Smith .  f - residual evaluated at x
1455e76c431SBarry Smith .  y - search direction (contains new iterate on output)
1465e76c431SBarry Smith .  w - work vector
1475e76c431SBarry Smith .  fnorm - 2-norm of f
1485e76c431SBarry Smith 
149c4a48953SLois Curfman McInnes    Output Parameters:
1505e76c431SBarry Smith .  g - residual evaluated at new iterate y
1515e76c431SBarry Smith .  y - new iterate (contains search direction on input)
1525e76c431SBarry Smith .  gnorm - 2-norm of g
1535e76c431SBarry Smith .  ynorm - 2-norm of search length
154761aaf1bSLois Curfman McInnes .  flag - set to 0, indicating a successful line search
1555e76c431SBarry Smith 
156c4a48953SLois Curfman McInnes    Options Database Key:
15709d61ba7SLois Curfman McInnes $  -snes_eq_ls basic
158c4a48953SLois Curfman McInnes 
15928ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
16028ae5a21SLois Curfman McInnes 
161f59ffdedSLois Curfman McInnes .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
16277c4ece6SBarry Smith           SNESSetLineSearch()
1635e76c431SBarry Smith @*/
1645e42470aSBarry Smith int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
165761aaf1bSLois Curfman McInnes                      double fnorm, double *ynorm, double *gnorm,int *flag )
1665e76c431SBarry Smith {
1675e42470aSBarry Smith   int    ierr;
1685334005bSBarry Smith   Scalar mone = -1.0;
1695334005bSBarry Smith 
170761aaf1bSLois Curfman McInnes   *flag = 0;
1717857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
172cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);       /* ynorm = || y || */
173ea4d3ed3SLois Curfman McInnes   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
174ea4d3ed3SLois Curfman McInnes   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
175cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);       /* gnorm = || g || */
1767857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
177761aaf1bSLois Curfman McInnes   return 0;
1785e76c431SBarry Smith }
1795e76c431SBarry Smith /* ------------------------------------------------------------------ */
1805615d1e5SSatish Balay #undef __FUNC__
18129e0b56fSBarry Smith #define __FUNC__ "SNESNoLineSearchNoNorms"
18229e0b56fSBarry Smith /*ARGSUSED*/
18329e0b56fSBarry Smith /*@C
18429e0b56fSBarry Smith    SNESNoLineSearchNoNorms - This routine is not a line search at
18529e0b56fSBarry Smith    all; it simply uses the full Newton step. This version does not
18629e0b56fSBarry Smith    even compute the norm of the function or search direction; this
18729e0b56fSBarry Smith    is intended only when you know the full step is fine and are
18829e0b56fSBarry Smith    not checking for convergence of the nonlinear iteration (for
18929e0b56fSBarry Smith    example, you are running always for a fixed number of Newton
19029e0b56fSBarry Smith    steps).
19129e0b56fSBarry Smith 
19229e0b56fSBarry Smith    Input Parameters:
19329e0b56fSBarry Smith .  snes - nonlinear context
19429e0b56fSBarry Smith .  x - current iterate
19529e0b56fSBarry Smith .  f - residual evaluated at x
19629e0b56fSBarry Smith .  y - search direction (contains new iterate on output)
19729e0b56fSBarry Smith .  w - work vector
19829e0b56fSBarry Smith .  fnorm - 2-norm of f
19929e0b56fSBarry Smith 
20029e0b56fSBarry Smith    Output Parameters:
20129e0b56fSBarry Smith .  g - residual evaluated at new iterate y
20229e0b56fSBarry Smith .  gnorm - not changed
20329e0b56fSBarry Smith .  ynorm - not changed
20429e0b56fSBarry Smith .  flag - set to 0, indicating a successful line search
20529e0b56fSBarry Smith 
20629e0b56fSBarry Smith    Options Database Key:
20729e0b56fSBarry Smith $  -snes_eq_ls basicnonorms
20829e0b56fSBarry Smith 
20929e0b56fSBarry Smith .keywords: SNES, nonlinear, line search, cubic
21029e0b56fSBarry Smith 
21129e0b56fSBarry Smith .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
21229e0b56fSBarry Smith           SNESSetLineSearch(), SNESNoLineSearch()
21329e0b56fSBarry Smith @*/
21429e0b56fSBarry Smith int SNESNoLineSearchNoNorms(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
21529e0b56fSBarry Smith                      double fnorm, double *ynorm, double *gnorm,int *flag )
21629e0b56fSBarry Smith {
21729e0b56fSBarry Smith   int    ierr;
21829e0b56fSBarry Smith   Scalar mone = -1.0;
21929e0b56fSBarry Smith 
22029e0b56fSBarry Smith   *flag = 0;
22129e0b56fSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
22229e0b56fSBarry Smith   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
22329e0b56fSBarry Smith   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
22429e0b56fSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
22529e0b56fSBarry Smith   return 0;
22629e0b56fSBarry Smith }
22729e0b56fSBarry Smith /* ------------------------------------------------------------------ */
22829e0b56fSBarry Smith #undef __FUNC__
2295615d1e5SSatish Balay #define __FUNC__ "SNESCubicLineSearch"
2304b828684SBarry Smith /*@C
231f525115eSLois Curfman McInnes    SNESCubicLineSearch - Performs a cubic line search (default line search method).
2325e76c431SBarry Smith 
2335e76c431SBarry Smith    Input Parameters:
2345e42470aSBarry Smith .  snes - nonlinear context
2355e76c431SBarry Smith .  x - current iterate
2365e76c431SBarry Smith .  f - residual evaluated at x
2375e76c431SBarry Smith .  y - search direction (contains new iterate on output)
2385e76c431SBarry Smith .  w - work vector
2395e76c431SBarry Smith .  fnorm - 2-norm of f
2405e76c431SBarry Smith 
241393d2d9aSLois Curfman McInnes    Output Parameters:
2425e76c431SBarry Smith .  g - residual evaluated at new iterate y
2435e76c431SBarry Smith .  y - new iterate (contains search direction on input)
2445e76c431SBarry Smith .  gnorm - 2-norm of g
2455e76c431SBarry Smith .  ynorm - 2-norm of search length
246761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
2475e76c431SBarry Smith 
248c4a48953SLois Curfman McInnes    Options Database Key:
24909d61ba7SLois Curfman McInnes $  -snes_eq_ls cubic
250c4a48953SLois Curfman McInnes 
2515e76c431SBarry Smith    Notes:
2525e76c431SBarry Smith    This line search is taken from "Numerical Methods for Unconstrained
2535e76c431SBarry Smith    Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325.
2545e76c431SBarry Smith 
25528ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
25628ae5a21SLois Curfman McInnes 
25777c4ece6SBarry Smith .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
2585e76c431SBarry Smith @*/
2595e42470aSBarry Smith int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w,
260761aaf1bSLois Curfman McInnes                         double fnorm,double *ynorm,double *gnorm,int *flag)
2615e76c431SBarry Smith {
262406556e6SLois Curfman McInnes   /*
263406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
264406556e6SLois Curfman McInnes      minimization problem:
265406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
266406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
267406556e6SLois Curfman McInnes    */
268406556e6SLois Curfman McInnes 
269ddd12767SBarry Smith   double  steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2;
270ea4d3ed3SLois Curfman McInnes   double  maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg;
2716b5873e3SBarry Smith #if defined(PETSC_COMPLEX)
2725e42470aSBarry Smith   Scalar  cinitslope, clambda;
2736b5873e3SBarry Smith #endif
2745e42470aSBarry Smith   int     ierr, count;
2755e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
2765334005bSBarry Smith   Scalar  mone = -1.0,scale;
2775e76c431SBarry Smith 
2787857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
279761aaf1bSLois Curfman McInnes   *flag   = 0;
2805e76c431SBarry Smith   alpha   = neP->alpha;
2815e76c431SBarry Smith   maxstep = neP->maxstep;
2825e76c431SBarry Smith   steptol = neP->steptol;
2835e76c431SBarry Smith 
284cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);
285a1c2b6eeSLois Curfman McInnes   if (*ynorm < snes->atol) {
286a1c2b6eeSLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Search direction and size are nearly 0\n");
287a1c2b6eeSLois Curfman McInnes     *gnorm = fnorm;
288a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
289a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
290ad922ac9SBarry Smith     goto theend1;
29194a9d846SBarry Smith   }
2925e76c431SBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
2935e42470aSBarry Smith     scale = maxstep/(*ynorm);
2946b5873e3SBarry Smith #if defined(PETSC_COMPLEX)
29594a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale));
2966b5873e3SBarry Smith #else
29794a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale);
2986b5873e3SBarry Smith #endif
299393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
3005e76c431SBarry Smith     *ynorm = maxstep;
3015e76c431SBarry Smith   }
3025e76c431SBarry Smith   minlambda = steptol/(*ynorm);
303a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
3045e42470aSBarry Smith #if defined(PETSC_COMPLEX)
305a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
3065e42470aSBarry Smith   initslope = real(cinitslope);
3075e42470aSBarry Smith #else
308a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
3095e42470aSBarry Smith #endif
3105e76c431SBarry Smith   if (initslope > 0.0) initslope = -initslope;
3115e76c431SBarry Smith   if (initslope == 0.0) initslope = -1.0;
3125e76c431SBarry Smith 
313393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
3145334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
31578b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
316cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm);
317406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
318393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
31994a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Using full step\n");
320ad922ac9SBarry Smith     goto theend1;
3215e76c431SBarry Smith   }
3225e76c431SBarry Smith 
3235e76c431SBarry Smith   /* Fit points with quadratic */
3245e76c431SBarry Smith   lambda = 1.0; count = 0;
325a703fe33SLois Curfman McInnes   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
3265e76c431SBarry Smith   lambdaprev = lambda;
3275e76c431SBarry Smith   gnormprev = *gnorm;
328ddd12767SBarry Smith   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
329ddd12767SBarry Smith   else lambda = lambdatemp;
330393d2d9aSLois Curfman McInnes   ierr   = VecCopy(x,w); CHKERRQ(ierr);
331ea4d3ed3SLois Curfman McInnes   lambdaneg = -lambda;
3325e42470aSBarry Smith #if defined(PETSC_COMPLEX)
333ea4d3ed3SLois Curfman McInnes   clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3345e42470aSBarry Smith #else
335ea4d3ed3SLois Curfman McInnes   ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3365e42470aSBarry Smith #endif
33778b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
338cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
339406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
340393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
341ea4d3ed3SLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda);
342ad922ac9SBarry Smith     goto theend1;
3435e76c431SBarry Smith   }
3445e76c431SBarry Smith 
3455e76c431SBarry Smith   /* Fit points with cubic */
3465e76c431SBarry Smith   count = 1;
3475e76c431SBarry Smith   while (1) {
3485e76c431SBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
3492b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:Unable to find good step length! %d \n",count);
3502b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
351ea4d3ed3SLois Curfman McInnes                fnorm,*gnorm,*ynorm,lambda,initslope);
352393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
353761aaf1bSLois Curfman McInnes       *flag = -1; break;
3545e76c431SBarry Smith     }
355406556e6SLois Curfman McInnes     t1 = ((*gnorm)*(*gnorm) - fnorm*fnorm)*0.5 - lambda*initslope;
356406556e6SLois Curfman McInnes     t2 = (gnormprev*gnormprev  - fnorm*fnorm)*0.5 - lambdaprev*initslope;
357ddd12767SBarry Smith     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3582b022350SLois Curfman McInnes     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3595e76c431SBarry Smith     d  = b*b - 3*a*initslope;
3605e76c431SBarry Smith     if (d < 0.0) d = 0.0;
3615e76c431SBarry Smith     if (a == 0.0) {
3625e76c431SBarry Smith       lambdatemp = -initslope/(2.0*b);
3635e76c431SBarry Smith     } else {
3645e76c431SBarry Smith       lambdatemp = (-b + sqrt(d))/(3.0*a);
3655e76c431SBarry Smith     }
3665e76c431SBarry Smith     if (lambdatemp > .5*lambda) {
3675e76c431SBarry Smith       lambdatemp = .5*lambda;
3685e76c431SBarry Smith     }
3695e76c431SBarry Smith     lambdaprev = lambda;
3705e76c431SBarry Smith     gnormprev = *gnorm;
3715e76c431SBarry Smith     if (lambdatemp <= .1*lambda) {
3725e76c431SBarry Smith       lambda = .1*lambda;
3735e76c431SBarry Smith     }
3745e76c431SBarry Smith     else lambda = lambdatemp;
375393d2d9aSLois Curfman McInnes     ierr = VecCopy( x, w ); CHKERRQ(ierr);
376ea4d3ed3SLois Curfman McInnes     lambdaneg = -lambda;
3775e42470aSBarry Smith #if defined(PETSC_COMPLEX)
378ea4d3ed3SLois Curfman McInnes     clambda = lambdaneg;
379393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3805e42470aSBarry Smith #else
381ea4d3ed3SLois Curfman McInnes     ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3825e42470aSBarry Smith #endif
38378b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
384cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
385406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* is reduction enough? */
386393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
387ea4d3ed3SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda);
3882715565aSLois Curfman McInnes       goto theend1;
3892b022350SLois Curfman McInnes     } else {
3902b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubic step no good, shrinking lambda,  lambda=%g\n",lambda);
3915e76c431SBarry Smith     }
3925e76c431SBarry Smith     count++;
3935e76c431SBarry Smith   }
394ad922ac9SBarry Smith   theend1:
3957857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
3965e42470aSBarry Smith   return 0;
3975e76c431SBarry Smith }
39852392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
3995615d1e5SSatish Balay #undef __FUNC__
4005615d1e5SSatish Balay #define __FUNC__ "SNESQuadraticLineSearch"
4014b828684SBarry Smith /*@C
402f525115eSLois Curfman McInnes    SNESQuadraticLineSearch - Performs a quadratic line search.
4035e76c431SBarry Smith 
4045e42470aSBarry Smith    Input Parameters:
405f59ffdedSLois Curfman McInnes .  snes - the SNES context
4065e42470aSBarry Smith .  x - current iterate
4075e42470aSBarry Smith .  f - residual evaluated at x
4085e42470aSBarry Smith .  y - search direction (contains new iterate on output)
4095e42470aSBarry Smith .  w - work vector
4105e42470aSBarry Smith .  fnorm - 2-norm of f
4115e42470aSBarry Smith 
412c4a48953SLois Curfman McInnes    Output Parameters:
4135e42470aSBarry Smith .  g - residual evaluated at new iterate y
4145e42470aSBarry Smith .  y - new iterate (contains search direction on input)
4155e42470aSBarry Smith .  gnorm - 2-norm of g
4165e42470aSBarry Smith .  ynorm - 2-norm of search length
417761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
4185e42470aSBarry Smith 
419c4a48953SLois Curfman McInnes    Options Database Key:
42009d61ba7SLois Curfman McInnes $  -snes_eq_ls quadratic
421c4a48953SLois Curfman McInnes 
4225e42470aSBarry Smith    Notes:
42377c4ece6SBarry Smith    Use SNESSetLineSearch()
424f63b844aSLois Curfman McInnes    to set this routine within the SNES_EQ_LS method.
4255e42470aSBarry Smith 
426f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, quadratic, line search
427f59ffdedSLois Curfman McInnes 
42877c4ece6SBarry Smith .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
4295e42470aSBarry Smith @*/
4305e42470aSBarry Smith int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
431761aaf1bSLois Curfman McInnes                            double fnorm, double *ynorm, double *gnorm,int *flag)
4325e76c431SBarry Smith {
433406556e6SLois Curfman McInnes   /*
434406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
435406556e6SLois Curfman McInnes      minimization problem:
436406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
437406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
438406556e6SLois Curfman McInnes    */
439ddd12767SBarry Smith   double  steptol,initslope,lambdaprev,gnormprev,maxstep,minlambda,alpha,lambda,lambdatemp;
4406b5873e3SBarry Smith #if defined(PETSC_COMPLEX)
4415e42470aSBarry Smith   Scalar  cinitslope,clambda;
4426b5873e3SBarry Smith #endif
4435e42470aSBarry Smith   int     ierr,count;
4445e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
4455334005bSBarry Smith   Scalar  mone = -1.0,scale;
4465e76c431SBarry Smith 
4477857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
448761aaf1bSLois Curfman McInnes   *flag = 0;
4495e42470aSBarry Smith   alpha   = neP->alpha;
4505e42470aSBarry Smith   maxstep = neP->maxstep;
4515e42470aSBarry Smith   steptol = neP->steptol;
4525e76c431SBarry Smith 
453cddf8d76SBarry Smith   VecNorm(y, NORM_2,ynorm );
454b37302c6SLois Curfman McInnes   if (*ynorm < snes->atol) {
45594a9d846SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n");
456b37302c6SLois Curfman McInnes     *gnorm = fnorm;
457b37302c6SLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
458b37302c6SLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
459ad922ac9SBarry Smith     goto theend2;
46094a9d846SBarry Smith   }
4615e42470aSBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
4625e42470aSBarry Smith     scale = maxstep/(*ynorm);
463393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
4645e42470aSBarry Smith     *ynorm = maxstep;
4655e76c431SBarry Smith   }
4665e42470aSBarry Smith   minlambda = steptol/(*ynorm);
467a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
4685e42470aSBarry Smith #if defined(PETSC_COMPLEX)
469a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
4705e42470aSBarry Smith   initslope = real(cinitslope);
4715e42470aSBarry Smith #else
472a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
4735e42470aSBarry Smith #endif
4745e42470aSBarry Smith   if (initslope > 0.0) initslope = -initslope;
4755e42470aSBarry Smith   if (initslope == 0.0) initslope = -1.0;
4765e42470aSBarry Smith 
477393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
4785334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
47978b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
480cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
481406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
482393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
48394a424c1SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n");
484ad922ac9SBarry Smith     goto theend2;
4855e42470aSBarry Smith   }
4865e42470aSBarry Smith 
4875e42470aSBarry Smith   /* Fit points with quadratic */
4885e42470aSBarry Smith   lambda = 1.0; count = 0;
4895e42470aSBarry Smith   count = 1;
4905e42470aSBarry Smith   while (1) {
4915e42470aSBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
49294a424c1SBarry Smith       PLogInfo(snes,
4934b828684SBarry Smith           "SNESQuadraticLineSearch:Unable to find good step length! %d \n",count);
49494a424c1SBarry Smith       PLogInfo(snes,
495ea4d3ed3SLois Curfman McInnes       "SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
496ea4d3ed3SLois Curfman McInnes           fnorm,*gnorm,*ynorm,lambda,initslope);
497393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
498761aaf1bSLois Curfman McInnes       *flag = -1; break;
4995e42470aSBarry Smith     }
500a703fe33SLois Curfman McInnes     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
5015e42470aSBarry Smith     lambdaprev = lambda;
5025e42470aSBarry Smith     gnormprev = *gnorm;
5035e42470aSBarry Smith     if (lambdatemp <= .1*lambda) {
5045e42470aSBarry Smith       lambda = .1*lambda;
5055e42470aSBarry Smith     } else lambda = lambdatemp;
506393d2d9aSLois Curfman McInnes     ierr = VecCopy(x,w); CHKERRQ(ierr);
5075334005bSBarry Smith     lambda = -lambda;
5085e42470aSBarry Smith #if defined(PETSC_COMPLEX)
509393d2d9aSLois Curfman McInnes     clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
5105e42470aSBarry Smith #else
511393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr);
5125e42470aSBarry Smith #endif
51378b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
514cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
515406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
516393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
51794a424c1SBarry Smith       PLogInfo(snes,
518ea4d3ed3SLois Curfman McInnes         "SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda);
51906259719SBarry Smith       break;
5205e42470aSBarry Smith     }
5215e42470aSBarry Smith     count++;
5225e42470aSBarry Smith   }
523ad922ac9SBarry Smith   theend2:
5247857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
5255e42470aSBarry Smith   return 0;
5265e76c431SBarry Smith }
5275e76c431SBarry Smith /* ------------------------------------------------------------ */
5285615d1e5SSatish Balay #undef __FUNC__
529*d4bb536fSBarry Smith #define __FUNC__ "SNESSetLineSearch"
530c9e6a524SLois Curfman McInnes /*@C
53177c4ece6SBarry Smith    SNESSetLineSearch - Sets the line search routine to be used
532f63b844aSLois Curfman McInnes    by the method SNES_EQ_LS.
5335e76c431SBarry Smith 
5345e76c431SBarry Smith    Input Parameters:
535eafb4bcbSBarry Smith .  snes - nonlinear context obtained from SNESCreate()
5365e76c431SBarry Smith .  func - pointer to int function
5375e76c431SBarry Smith 
538c4a48953SLois Curfman McInnes    Available Routines:
539f59ffdedSLois Curfman McInnes .  SNESCubicLineSearch() - default line search
540f59ffdedSLois Curfman McInnes .  SNESQuadraticLineSearch() - quadratic line search
541f59ffdedSLois Curfman McInnes .  SNESNoLineSearch() - the full Newton step (actually not a line search)
5425e76c431SBarry Smith 
543c4a48953SLois Curfman McInnes     Options Database Keys:
54409d61ba7SLois Curfman McInnes $   -snes_eq_ls [basic,quadratic,cubic]
545912ebf9aSLois Curfman McInnes $   -snes_eq_ls_alpha <alpha>
546912ebf9aSLois Curfman McInnes $   -snes_eq_ls_maxstep <max>
547912ebf9aSLois Curfman McInnes $   -snes_eq_ls_steptol <steptol>
548c4a48953SLois Curfman McInnes 
5495e76c431SBarry Smith    Calling sequence of func:
550f59ffdedSLois Curfman McInnes    func (SNES snes, Vec x, Vec f, Vec g, Vec y,
551761aaf1bSLois Curfman McInnes          Vec w, double fnorm, double *ynorm,
552761aaf1bSLois Curfman McInnes          double *gnorm, *flag)
5535e76c431SBarry Smith 
5545e76c431SBarry Smith     Input parameters for func:
5555e42470aSBarry Smith .   snes - nonlinear context
5565e76c431SBarry Smith .   x - current iterate
5575e76c431SBarry Smith .   f - residual evaluated at x
5585e76c431SBarry Smith .   y - search direction (contains new iterate on output)
5595e76c431SBarry Smith .   w - work vector
5605e76c431SBarry Smith .   fnorm - 2-norm of f
5615e76c431SBarry Smith 
5625e76c431SBarry Smith     Output parameters for func:
5635e76c431SBarry Smith .   g - residual evaluated at new iterate y
5645e76c431SBarry Smith .   y - new iterate (contains search direction on input)
5655e76c431SBarry Smith .   gnorm - 2-norm of g
5665e76c431SBarry Smith .   ynorm - 2-norm of search length
567761aaf1bSLois Curfman McInnes .   flag - set to 0 if the line search succeeds; a nonzero integer
568761aaf1bSLois Curfman McInnes            on failure.
569f59ffdedSLois Curfman McInnes 
570f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, set, line search, routine
571f59ffdedSLois Curfman McInnes 
572f59ffdedSLois Curfman McInnes .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch()
5735e76c431SBarry Smith @*/
57477c4ece6SBarry Smith int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec,
575761aaf1bSLois Curfman McInnes                              double,double*,double*,int*))
5765e76c431SBarry Smith {
577f63b844aSLois Curfman McInnes   if ((snes)->type == SNES_EQ_LS) ((SNES_LS *)(snes->data))->LineSearch = func;
5785e42470aSBarry Smith   return 0;
5795e76c431SBarry Smith }
58052392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
5815615d1e5SSatish Balay #undef __FUNC__
582*d4bb536fSBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS"
583f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p)
5845e42470aSBarry Smith {
5855e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
5866daaf66cSBarry Smith 
587f63b844aSLois Curfman McInnes   PetscPrintf(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n");
58809d61ba7SLois Curfman McInnes   PetscPrintf(snes->comm,"   %ssnes_eq_ls [basic,quadratic,cubic]\n",p);
58909d61ba7SLois Curfman McInnes   PetscPrintf(snes->comm,"   %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha);
59009d61ba7SLois Curfman McInnes   PetscPrintf(snes->comm,"   %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep);
59109d61ba7SLois Curfman McInnes   PetscPrintf(snes->comm,"   %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol);
5926b5873e3SBarry Smith   return 0;
5935e42470aSBarry Smith }
59452392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
5955615d1e5SSatish Balay #undef __FUNC__
596*d4bb536fSBarry Smith #define __FUNC__ "SNESView_EQ_LS"
597f63b844aSLois Curfman McInnes static int SNESView_EQ_LS(PetscObject obj,Viewer viewer)
598a935fc98SLois Curfman McInnes {
599a935fc98SLois Curfman McInnes   SNES       snes = (SNES)obj;
600a935fc98SLois Curfman McInnes   SNES_LS    *ls = (SNES_LS *)snes->data;
601d636dbe3SBarry Smith   FILE       *fd;
60219bcc07fSBarry Smith   char       *cstr;
60351695f54SLois Curfman McInnes   int        ierr;
60419bcc07fSBarry Smith   ViewerType vtype;
605a935fc98SLois Curfman McInnes 
60619bcc07fSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
60719bcc07fSBarry Smith   if (vtype  == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
60890ace30eSBarry Smith     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
60919bcc07fSBarry Smith     if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch";
61019bcc07fSBarry Smith     else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch";
61119bcc07fSBarry Smith     else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch";
61219bcc07fSBarry Smith     else cstr = "unknown";
61377c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    line search variant: %s\n",cstr);
61477c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    alpha=%g, maxstep=%g, steptol=%g\n",
615a935fc98SLois Curfman McInnes                  ls->alpha,ls->maxstep,ls->steptol);
61619bcc07fSBarry Smith   }
617a935fc98SLois Curfman McInnes   return 0;
618a935fc98SLois Curfman McInnes }
61952392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6205615d1e5SSatish Balay #undef __FUNC__
6215615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS"
622f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes)
6235e42470aSBarry Smith {
6245e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
6255e42470aSBarry Smith   char    ver[16];
6265e42470aSBarry Smith   double  tmp;
62725cdf11fSBarry Smith   int     ierr,flg;
6285e42470aSBarry Smith 
62909d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr);
63025cdf11fSBarry Smith   if (flg) {
6315e42470aSBarry Smith     ls->alpha = tmp;
6325e42470aSBarry Smith   }
63309d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr);
63425cdf11fSBarry Smith   if (flg) {
6355e42470aSBarry Smith     ls->maxstep = tmp;
6365e42470aSBarry Smith   }
63709d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr);
63825cdf11fSBarry Smith   if (flg) {
6395e42470aSBarry Smith     ls->steptol = tmp;
6405e42470aSBarry Smith   }
64109d61ba7SLois Curfman McInnes   ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr);
64225cdf11fSBarry Smith   if (flg) {
64348d91487SBarry Smith     if (!PetscStrcmp(ver,"basic")) {
64477c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearch);
6455e42470aSBarry Smith     }
64629e0b56fSBarry Smith     else if (!PetscStrcmp(ver,"basicnonorms")) {
64729e0b56fSBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearchNoNorms);
64829e0b56fSBarry Smith     }
64948d91487SBarry Smith     else if (!PetscStrcmp(ver,"quadratic")) {
65077c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESQuadraticLineSearch);
6515e42470aSBarry Smith     }
65248d91487SBarry Smith     else if (!PetscStrcmp(ver,"cubic")) {
65377c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESCubicLineSearch);
6545e42470aSBarry Smith     }
655e3372554SBarry Smith     else {SETERRQ(1,0,"Unknown line search");}
6565e42470aSBarry Smith   }
6575e42470aSBarry Smith   return 0;
6585e42470aSBarry Smith }
6595e42470aSBarry Smith /* ------------------------------------------------------------ */
6605615d1e5SSatish Balay #undef __FUNC__
6615615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS"
662f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES  snes )
6635e42470aSBarry Smith {
6645e42470aSBarry Smith   SNES_LS *neP;
6655e42470aSBarry Smith 
66629e0b56fSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) SETERRQ(1,0,"For SNES_NONLINEAR_EQUATIONS only");
667f63b844aSLois Curfman McInnes   snes->type		= SNES_EQ_LS;
668f63b844aSLois Curfman McInnes   snes->setup		= SNESSetUp_EQ_LS;
669f63b844aSLois Curfman McInnes   snes->solve		= SNESSolve_EQ_LS;
670f63b844aSLois Curfman McInnes   snes->destroy		= SNESDestroy_EQ_LS;
671f63b844aSLois Curfman McInnes   snes->converged	= SNESConverged_EQ_LS;
672f63b844aSLois Curfman McInnes   snes->printhelp       = SNESPrintHelp_EQ_LS;
673f63b844aSLois Curfman McInnes   snes->setfromoptions  = SNESSetFromOptions_EQ_LS;
674f63b844aSLois Curfman McInnes   snes->view            = SNESView_EQ_LS;
6755baf8537SBarry Smith   snes->nwork           = 0;
6765e42470aSBarry Smith 
6770452661fSBarry Smith   neP			= PetscNew(SNES_LS);   CHKPTRQ(neP);
678ff782a9fSLois Curfman McInnes   PLogObjectMemory(snes,sizeof(SNES_LS));
6795e42470aSBarry Smith   snes->data    	= (void *) neP;
6805e42470aSBarry Smith   neP->alpha		= 1.e-4;
6815e42470aSBarry Smith   neP->maxstep		= 1.e8;
6825e42470aSBarry Smith   neP->steptol		= 1.e-12;
6835e42470aSBarry Smith   neP->LineSearch       = SNESCubicLineSearch;
6845e42470aSBarry Smith   return 0;
6855e42470aSBarry Smith }
6865e42470aSBarry Smith 
687