xref: /petsc/src/snes/impls/ls/ls.c (revision 76be9ce4a233aaa47cda2bc7f5a27cd7faabecaa)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*76be9ce4SBarry Smith static char vcid[] = "$Id: ls.c,v 1.98 1998/01/06 20:12:26 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"
124f63b844aSLois Curfman McInnes int SNESDestroy_EQ_LS(PetscObject obj)
1255e76c431SBarry Smith {
1265e42470aSBarry Smith   SNES snes = (SNES) obj;
127393d2d9aSLois Curfman McInnes   int  ierr;
1283a40ed3dSBarry Smith 
1293a40ed3dSBarry Smith   PetscFunctionBegin;
1305baf8537SBarry Smith   if (snes->nwork) {
1314b0e389bSBarry Smith     ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr);
13221c89e3eSBarry Smith   }
1330452661fSBarry Smith   PetscFree(snes->data);
1343a40ed3dSBarry Smith   PetscFunctionReturn(0);
1355e76c431SBarry Smith }
1365e76c431SBarry Smith /* ------------------------------------------------------------ */
1375615d1e5SSatish Balay #undef __FUNC__
1385615d1e5SSatish Balay #define __FUNC__ "SNESNoLineSearch"
1395e76c431SBarry Smith /*ARGSUSED*/
1404b828684SBarry Smith /*@C
1415e42470aSBarry Smith    SNESNoLineSearch - This routine is not a line search at all;
1425e76c431SBarry Smith    it simply uses the full Newton step.  Thus, this routine is intended
1435e76c431SBarry Smith    to serve as a template and is not recommended for general use.
1445e76c431SBarry Smith 
1455e76c431SBarry Smith    Input Parameters:
1465e42470aSBarry Smith .  snes - nonlinear context
1475e76c431SBarry Smith .  x - current iterate
1485e76c431SBarry Smith .  f - residual evaluated at x
1495e76c431SBarry Smith .  y - search direction (contains new iterate on output)
1505e76c431SBarry Smith .  w - work vector
1515e76c431SBarry Smith .  fnorm - 2-norm of f
1525e76c431SBarry Smith 
153c4a48953SLois Curfman McInnes    Output Parameters:
1545e76c431SBarry Smith .  g - residual evaluated at new iterate y
1555e76c431SBarry Smith .  y - new iterate (contains search direction on input)
1565e76c431SBarry Smith .  gnorm - 2-norm of g
1575e76c431SBarry Smith .  ynorm - 2-norm of search length
158761aaf1bSLois Curfman McInnes .  flag - set to 0, indicating a successful line search
1595e76c431SBarry Smith 
160c4a48953SLois Curfman McInnes    Options Database Key:
16109d61ba7SLois Curfman McInnes $  -snes_eq_ls basic
162c4a48953SLois Curfman McInnes 
16328ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
16428ae5a21SLois Curfman McInnes 
165f59ffdedSLois Curfman McInnes .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
16677c4ece6SBarry Smith           SNESSetLineSearch()
1675e76c431SBarry Smith @*/
1685e42470aSBarry Smith int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
169761aaf1bSLois Curfman McInnes                      double fnorm, double *ynorm, double *gnorm,int *flag )
1705e76c431SBarry Smith {
1715e42470aSBarry Smith   int    ierr;
1725334005bSBarry Smith   Scalar mone = -1.0;
1735334005bSBarry Smith 
1743a40ed3dSBarry Smith   PetscFunctionBegin;
175761aaf1bSLois Curfman McInnes   *flag = 0;
1767857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
177cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);       /* ynorm = || y || */
178ea4d3ed3SLois Curfman McInnes   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
179ea4d3ed3SLois Curfman McInnes   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
180cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);       /* gnorm = || g || */
1817857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
1823a40ed3dSBarry Smith   PetscFunctionReturn(0);
1835e76c431SBarry Smith }
1845e76c431SBarry Smith /* ------------------------------------------------------------------ */
1855615d1e5SSatish Balay #undef __FUNC__
18629e0b56fSBarry Smith #define __FUNC__ "SNESNoLineSearchNoNorms"
18729e0b56fSBarry Smith /*ARGSUSED*/
18829e0b56fSBarry Smith /*@C
18929e0b56fSBarry Smith    SNESNoLineSearchNoNorms - This routine is not a line search at
19029e0b56fSBarry Smith    all; it simply uses the full Newton step. This version does not
19129e0b56fSBarry Smith    even compute the norm of the function or search direction; this
19229e0b56fSBarry Smith    is intended only when you know the full step is fine and are
19329e0b56fSBarry Smith    not checking for convergence of the nonlinear iteration (for
19429e0b56fSBarry Smith    example, you are running always for a fixed number of Newton
19529e0b56fSBarry Smith    steps).
19629e0b56fSBarry Smith 
19729e0b56fSBarry Smith    Input Parameters:
19829e0b56fSBarry Smith .  snes - nonlinear context
19929e0b56fSBarry Smith .  x - current iterate
20029e0b56fSBarry Smith .  f - residual evaluated at x
20129e0b56fSBarry Smith .  y - search direction (contains new iterate on output)
20229e0b56fSBarry Smith .  w - work vector
20329e0b56fSBarry Smith .  fnorm - 2-norm of f
20429e0b56fSBarry Smith 
20529e0b56fSBarry Smith    Output Parameters:
20629e0b56fSBarry Smith .  g - residual evaluated at new iterate y
20729e0b56fSBarry Smith .  gnorm - not changed
20829e0b56fSBarry Smith .  ynorm - not changed
20929e0b56fSBarry Smith .  flag - set to 0, indicating a successful line search
21029e0b56fSBarry Smith 
21129e0b56fSBarry Smith    Options Database Key:
21229e0b56fSBarry Smith $  -snes_eq_ls basicnonorms
21329e0b56fSBarry Smith 
21429e0b56fSBarry Smith .keywords: SNES, nonlinear, line search, cubic
21529e0b56fSBarry Smith 
21629e0b56fSBarry Smith .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
21729e0b56fSBarry Smith           SNESSetLineSearch(), SNESNoLineSearch()
21829e0b56fSBarry Smith @*/
21929e0b56fSBarry Smith int SNESNoLineSearchNoNorms(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
22029e0b56fSBarry Smith                      double fnorm, double *ynorm, double *gnorm,int *flag )
22129e0b56fSBarry Smith {
22229e0b56fSBarry Smith   int    ierr;
22329e0b56fSBarry Smith   Scalar mone = -1.0;
22429e0b56fSBarry Smith 
2253a40ed3dSBarry Smith   PetscFunctionBegin;
22629e0b56fSBarry Smith   *flag = 0;
22729e0b56fSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
22829e0b56fSBarry Smith   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
22929e0b56fSBarry Smith   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
23029e0b56fSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
2313a40ed3dSBarry Smith   PetscFunctionReturn(0);
23229e0b56fSBarry Smith }
23329e0b56fSBarry Smith /* ------------------------------------------------------------------ */
23429e0b56fSBarry Smith #undef __FUNC__
2355615d1e5SSatish Balay #define __FUNC__ "SNESCubicLineSearch"
2364b828684SBarry Smith /*@C
237f525115eSLois Curfman McInnes    SNESCubicLineSearch - Performs a cubic line search (default line search method).
2385e76c431SBarry Smith 
2395e76c431SBarry Smith    Input Parameters:
2405e42470aSBarry Smith .  snes - nonlinear context
2415e76c431SBarry Smith .  x - current iterate
2425e76c431SBarry Smith .  f - residual evaluated at x
2435e76c431SBarry Smith .  y - search direction (contains new iterate on output)
2445e76c431SBarry Smith .  w - work vector
2455e76c431SBarry Smith .  fnorm - 2-norm of f
2465e76c431SBarry Smith 
247393d2d9aSLois Curfman McInnes    Output Parameters:
2485e76c431SBarry Smith .  g - residual evaluated at new iterate y
2495e76c431SBarry Smith .  y - new iterate (contains search direction on input)
2505e76c431SBarry Smith .  gnorm - 2-norm of g
2515e76c431SBarry Smith .  ynorm - 2-norm of search length
252761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
2535e76c431SBarry Smith 
254c4a48953SLois Curfman McInnes    Options Database Key:
25509d61ba7SLois Curfman McInnes $  -snes_eq_ls cubic
256c4a48953SLois Curfman McInnes 
2575e76c431SBarry Smith    Notes:
2585e76c431SBarry Smith    This line search is taken from "Numerical Methods for Unconstrained
2595e76c431SBarry Smith    Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325.
2605e76c431SBarry Smith 
26128ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
26228ae5a21SLois Curfman McInnes 
26377c4ece6SBarry Smith .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
2645e76c431SBarry Smith @*/
2655e42470aSBarry Smith int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w,
266761aaf1bSLois Curfman McInnes                         double fnorm,double *ynorm,double *gnorm,int *flag)
2675e76c431SBarry Smith {
268406556e6SLois Curfman McInnes   /*
269406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
270406556e6SLois Curfman McInnes      minimization problem:
271406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
272406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
273406556e6SLois Curfman McInnes    */
274406556e6SLois Curfman McInnes 
275ddd12767SBarry Smith   double  steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2;
276ea4d3ed3SLois Curfman McInnes   double  maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg;
2773a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
2785e42470aSBarry Smith   Scalar  cinitslope, clambda;
2796b5873e3SBarry Smith #endif
2805e42470aSBarry Smith   int     ierr, count;
2815e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
2825334005bSBarry Smith   Scalar  mone = -1.0,scale;
2835e76c431SBarry Smith 
2843a40ed3dSBarry Smith   PetscFunctionBegin;
2857857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
286761aaf1bSLois Curfman McInnes   *flag   = 0;
2875e76c431SBarry Smith   alpha   = neP->alpha;
2885e76c431SBarry Smith   maxstep = neP->maxstep;
2895e76c431SBarry Smith   steptol = neP->steptol;
2905e76c431SBarry Smith 
291cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);
292a1c2b6eeSLois Curfman McInnes   if (*ynorm < snes->atol) {
293a1c2b6eeSLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Search direction and size are nearly 0\n");
294a1c2b6eeSLois Curfman McInnes     *gnorm = fnorm;
295a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
296a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
297ad922ac9SBarry Smith     goto theend1;
29894a9d846SBarry Smith   }
2995e76c431SBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
3005e42470aSBarry Smith     scale = maxstep/(*ynorm);
3013a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
30294a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale));
3036b5873e3SBarry Smith #else
30494a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale);
3056b5873e3SBarry Smith #endif
306393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
3075e76c431SBarry Smith     *ynorm = maxstep;
3085e76c431SBarry Smith   }
3095e76c431SBarry Smith   minlambda = steptol/(*ynorm);
310a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
3113a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
312a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
3135e42470aSBarry Smith   initslope = real(cinitslope);
3145e42470aSBarry Smith #else
315a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
3165e42470aSBarry Smith #endif
3175e76c431SBarry Smith   if (initslope > 0.0) initslope = -initslope;
3185e76c431SBarry Smith   if (initslope == 0.0) initslope = -1.0;
3195e76c431SBarry Smith 
320393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
3215334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
32278b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
323cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm);
324406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
325393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
32694a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Using full step\n");
327ad922ac9SBarry Smith     goto theend1;
3285e76c431SBarry Smith   }
3295e76c431SBarry Smith 
3305e76c431SBarry Smith   /* Fit points with quadratic */
3315e76c431SBarry Smith   lambda = 1.0; count = 0;
332a703fe33SLois Curfman McInnes   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
3335e76c431SBarry Smith   lambdaprev = lambda;
3345e76c431SBarry Smith   gnormprev = *gnorm;
335ddd12767SBarry Smith   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
336ddd12767SBarry Smith   else lambda = lambdatemp;
337393d2d9aSLois Curfman McInnes   ierr   = VecCopy(x,w); CHKERRQ(ierr);
338ea4d3ed3SLois Curfman McInnes   lambdaneg = -lambda;
3393a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
340ea4d3ed3SLois Curfman McInnes   clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3415e42470aSBarry Smith #else
342ea4d3ed3SLois Curfman McInnes   ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3435e42470aSBarry Smith #endif
34478b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
345cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
346406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
347393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
348ea4d3ed3SLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda);
349ad922ac9SBarry Smith     goto theend1;
3505e76c431SBarry Smith   }
3515e76c431SBarry Smith 
3525e76c431SBarry Smith   /* Fit points with cubic */
3535e76c431SBarry Smith   count = 1;
3545e76c431SBarry Smith   while (1) {
3555e76c431SBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
3562b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:Unable to find good step length! %d \n",count);
3572b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
358ea4d3ed3SLois Curfman McInnes                fnorm,*gnorm,*ynorm,lambda,initslope);
359393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
360761aaf1bSLois Curfman McInnes       *flag = -1; break;
3615e76c431SBarry Smith     }
362406556e6SLois Curfman McInnes     t1 = ((*gnorm)*(*gnorm) - fnorm*fnorm)*0.5 - lambda*initslope;
363406556e6SLois Curfman McInnes     t2 = (gnormprev*gnormprev  - fnorm*fnorm)*0.5 - lambdaprev*initslope;
364ddd12767SBarry Smith     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3652b022350SLois Curfman McInnes     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3665e76c431SBarry Smith     d  = b*b - 3*a*initslope;
3675e76c431SBarry Smith     if (d < 0.0) d = 0.0;
3685e76c431SBarry Smith     if (a == 0.0) {
3695e76c431SBarry Smith       lambdatemp = -initslope/(2.0*b);
3705e76c431SBarry Smith     } else {
3715e76c431SBarry Smith       lambdatemp = (-b + sqrt(d))/(3.0*a);
3725e76c431SBarry Smith     }
3735e76c431SBarry Smith     if (lambdatemp > .5*lambda) {
3745e76c431SBarry Smith       lambdatemp = .5*lambda;
3755e76c431SBarry Smith     }
3765e76c431SBarry Smith     lambdaprev = lambda;
3775e76c431SBarry Smith     gnormprev = *gnorm;
3785e76c431SBarry Smith     if (lambdatemp <= .1*lambda) {
3795e76c431SBarry Smith       lambda = .1*lambda;
3805e76c431SBarry Smith     }
3815e76c431SBarry Smith     else lambda = lambdatemp;
382393d2d9aSLois Curfman McInnes     ierr = VecCopy( x, w ); CHKERRQ(ierr);
383ea4d3ed3SLois Curfman McInnes     lambdaneg = -lambda;
3843a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
385ea4d3ed3SLois Curfman McInnes     clambda = lambdaneg;
386393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3875e42470aSBarry Smith #else
388ea4d3ed3SLois Curfman McInnes     ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3895e42470aSBarry Smith #endif
39078b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
391cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
392406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* is reduction enough? */
393393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
394ea4d3ed3SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda);
3952715565aSLois Curfman McInnes       goto theend1;
3962b022350SLois Curfman McInnes     } else {
3972b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubic step no good, shrinking lambda,  lambda=%g\n",lambda);
3985e76c431SBarry Smith     }
3995e76c431SBarry Smith     count++;
4005e76c431SBarry Smith   }
401ad922ac9SBarry Smith   theend1:
4027857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
4033a40ed3dSBarry Smith   PetscFunctionReturn(0);
4045e76c431SBarry Smith }
40552392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
4065615d1e5SSatish Balay #undef __FUNC__
4075615d1e5SSatish Balay #define __FUNC__ "SNESQuadraticLineSearch"
4084b828684SBarry Smith /*@C
409f525115eSLois Curfman McInnes    SNESQuadraticLineSearch - Performs a quadratic line search.
4105e76c431SBarry Smith 
4115e42470aSBarry Smith    Input Parameters:
412f59ffdedSLois Curfman McInnes .  snes - the SNES context
4135e42470aSBarry Smith .  x - current iterate
4145e42470aSBarry Smith .  f - residual evaluated at x
4155e42470aSBarry Smith .  y - search direction (contains new iterate on output)
4165e42470aSBarry Smith .  w - work vector
4175e42470aSBarry Smith .  fnorm - 2-norm of f
4185e42470aSBarry Smith 
419c4a48953SLois Curfman McInnes    Output Parameters:
4205e42470aSBarry Smith .  g - residual evaluated at new iterate y
4215e42470aSBarry Smith .  y - new iterate (contains search direction on input)
4225e42470aSBarry Smith .  gnorm - 2-norm of g
4235e42470aSBarry Smith .  ynorm - 2-norm of search length
424761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
4255e42470aSBarry Smith 
426c4a48953SLois Curfman McInnes    Options Database Key:
42709d61ba7SLois Curfman McInnes $  -snes_eq_ls quadratic
428c4a48953SLois Curfman McInnes 
4295e42470aSBarry Smith    Notes:
43077c4ece6SBarry Smith    Use SNESSetLineSearch()
431f63b844aSLois Curfman McInnes    to set this routine within the SNES_EQ_LS method.
4325e42470aSBarry Smith 
433f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, quadratic, line search
434f59ffdedSLois Curfman McInnes 
43577c4ece6SBarry Smith .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
4365e42470aSBarry Smith @*/
4375e42470aSBarry Smith int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
438761aaf1bSLois Curfman McInnes                            double fnorm, double *ynorm, double *gnorm,int *flag)
4395e76c431SBarry Smith {
440406556e6SLois Curfman McInnes   /*
441406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
442406556e6SLois Curfman McInnes      minimization problem:
443406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
444406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
445406556e6SLois Curfman McInnes    */
446ddd12767SBarry Smith   double  steptol,initslope,lambdaprev,gnormprev,maxstep,minlambda,alpha,lambda,lambdatemp;
4473a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
4485e42470aSBarry Smith   Scalar  cinitslope,clambda;
4496b5873e3SBarry Smith #endif
4505e42470aSBarry Smith   int     ierr,count;
4515e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
4525334005bSBarry Smith   Scalar  mone = -1.0,scale;
4535e76c431SBarry Smith 
4543a40ed3dSBarry Smith   PetscFunctionBegin;
4557857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
456761aaf1bSLois Curfman McInnes   *flag   = 0;
4575e42470aSBarry Smith   alpha   = neP->alpha;
4585e42470aSBarry Smith   maxstep = neP->maxstep;
4595e42470aSBarry Smith   steptol = neP->steptol;
4605e76c431SBarry Smith 
461cddf8d76SBarry Smith   VecNorm(y, NORM_2,ynorm );
462b37302c6SLois Curfman McInnes   if (*ynorm < snes->atol) {
46394a9d846SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n");
464b37302c6SLois Curfman McInnes     *gnorm = fnorm;
465b37302c6SLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
466b37302c6SLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
467ad922ac9SBarry Smith     goto theend2;
46894a9d846SBarry Smith   }
4695e42470aSBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
4705e42470aSBarry Smith     scale = maxstep/(*ynorm);
471393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
4725e42470aSBarry Smith     *ynorm = maxstep;
4735e76c431SBarry Smith   }
4745e42470aSBarry Smith   minlambda = steptol/(*ynorm);
475a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
4763a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
477a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
4785e42470aSBarry Smith   initslope = real(cinitslope);
4795e42470aSBarry Smith #else
480a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
4815e42470aSBarry Smith #endif
4825e42470aSBarry Smith   if (initslope > 0.0) initslope = -initslope;
4835e42470aSBarry Smith   if (initslope == 0.0) initslope = -1.0;
4845e42470aSBarry Smith 
485393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
4865334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
48778b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
488cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
489406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
490393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
49194a424c1SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n");
492ad922ac9SBarry Smith     goto theend2;
4935e42470aSBarry Smith   }
4945e42470aSBarry Smith 
4955e42470aSBarry Smith   /* Fit points with quadratic */
4965e42470aSBarry Smith   lambda = 1.0; count = 0;
4975e42470aSBarry Smith   count = 1;
4985e42470aSBarry Smith   while (1) {
4995e42470aSBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
500981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:Unable to find good step length! %d \n",count);
501981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
502ea4d3ed3SLois Curfman McInnes                fnorm,*gnorm,*ynorm,lambda,initslope);
503393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
504761aaf1bSLois Curfman McInnes       *flag = -1; break;
5055e42470aSBarry Smith     }
506a703fe33SLois Curfman McInnes     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
5075e42470aSBarry Smith     lambdaprev = lambda;
5085e42470aSBarry Smith     gnormprev = *gnorm;
5095e42470aSBarry Smith     if (lambdatemp <= .1*lambda) {
5105e42470aSBarry Smith       lambda = .1*lambda;
5115e42470aSBarry Smith     } else lambda = lambdatemp;
512393d2d9aSLois Curfman McInnes     ierr = VecCopy(x,w); CHKERRQ(ierr);
5135334005bSBarry Smith     lambda = -lambda;
5143a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
515393d2d9aSLois Curfman McInnes     clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
5165e42470aSBarry Smith #else
517393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr);
5185e42470aSBarry Smith #endif
51978b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
520cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
521406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
522393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
523981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda);
52406259719SBarry Smith       break;
5255e42470aSBarry Smith     }
5265e42470aSBarry Smith     count++;
5275e42470aSBarry Smith   }
528ad922ac9SBarry Smith   theend2:
5297857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
5303a40ed3dSBarry Smith   PetscFunctionReturn(0);
5315e76c431SBarry Smith }
5325e76c431SBarry Smith /* ------------------------------------------------------------ */
5335615d1e5SSatish Balay #undef __FUNC__
534d4bb536fSBarry Smith #define __FUNC__ "SNESSetLineSearch"
535c9e6a524SLois Curfman McInnes /*@C
53677c4ece6SBarry Smith    SNESSetLineSearch - Sets the line search routine to be used
537f63b844aSLois Curfman McInnes    by the method SNES_EQ_LS.
5385e76c431SBarry Smith 
5395e76c431SBarry Smith    Input Parameters:
540eafb4bcbSBarry Smith .  snes - nonlinear context obtained from SNESCreate()
5415e76c431SBarry Smith .  func - pointer to int function
5425e76c431SBarry Smith 
543c4a48953SLois Curfman McInnes    Available Routines:
544f59ffdedSLois Curfman McInnes .  SNESCubicLineSearch() - default line search
545f59ffdedSLois Curfman McInnes .  SNESQuadraticLineSearch() - quadratic line search
546f59ffdedSLois Curfman McInnes .  SNESNoLineSearch() - the full Newton step (actually not a line search)
5475e76c431SBarry Smith 
548c4a48953SLois Curfman McInnes     Options Database Keys:
54909d61ba7SLois Curfman McInnes $   -snes_eq_ls [basic,quadratic,cubic]
550912ebf9aSLois Curfman McInnes $   -snes_eq_ls_alpha <alpha>
551912ebf9aSLois Curfman McInnes $   -snes_eq_ls_maxstep <max>
552912ebf9aSLois Curfman McInnes $   -snes_eq_ls_steptol <steptol>
553c4a48953SLois Curfman McInnes 
5545e76c431SBarry Smith    Calling sequence of func:
555f59ffdedSLois Curfman McInnes    func (SNES snes, Vec x, Vec f, Vec g, Vec y,
556761aaf1bSLois Curfman McInnes          Vec w, double fnorm, double *ynorm,
557761aaf1bSLois Curfman McInnes          double *gnorm, *flag)
5585e76c431SBarry Smith 
5595e76c431SBarry Smith     Input parameters for func:
5605e42470aSBarry Smith .   snes - nonlinear context
5615e76c431SBarry Smith .   x - current iterate
5625e76c431SBarry Smith .   f - residual evaluated at x
5635e76c431SBarry Smith .   y - search direction (contains new iterate on output)
5645e76c431SBarry Smith .   w - work vector
5655e76c431SBarry Smith .   fnorm - 2-norm of f
5665e76c431SBarry Smith 
5675e76c431SBarry Smith     Output parameters for func:
5685e76c431SBarry Smith .   g - residual evaluated at new iterate y
5695e76c431SBarry Smith .   y - new iterate (contains search direction on input)
5705e76c431SBarry Smith .   gnorm - 2-norm of g
5715e76c431SBarry Smith .   ynorm - 2-norm of search length
572761aaf1bSLois Curfman McInnes .   flag - set to 0 if the line search succeeds; a nonzero integer
573761aaf1bSLois Curfman McInnes            on failure.
574f59ffdedSLois Curfman McInnes 
575f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, set, line search, routine
576f59ffdedSLois Curfman McInnes 
577f59ffdedSLois Curfman McInnes .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch()
5785e76c431SBarry Smith @*/
57977c4ece6SBarry Smith int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec,
580761aaf1bSLois Curfman McInnes                              double,double*,double*,int*))
5815e76c431SBarry Smith {
5823a40ed3dSBarry Smith   PetscFunctionBegin;
583f63b844aSLois Curfman McInnes   if ((snes)->type == SNES_EQ_LS) ((SNES_LS *)(snes->data))->LineSearch = func;
5843a40ed3dSBarry Smith   PetscFunctionReturn(0);
5855e76c431SBarry Smith }
58652392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
5875615d1e5SSatish Balay #undef __FUNC__
588d4bb536fSBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS"
589f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p)
5905e42470aSBarry Smith {
5915e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
5926daaf66cSBarry Smith 
5933a40ed3dSBarry Smith   PetscFunctionBegin;
594*76be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n");
595*76be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls [basic,quadratic,cubic]\n",p);
596*76be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha);
597*76be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep);
598*76be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol);
5993a40ed3dSBarry Smith   PetscFunctionReturn(0);
6005e42470aSBarry Smith }
60152392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6025615d1e5SSatish Balay #undef __FUNC__
603d4bb536fSBarry Smith #define __FUNC__ "SNESView_EQ_LS"
604f63b844aSLois Curfman McInnes static int SNESView_EQ_LS(PetscObject obj,Viewer viewer)
605a935fc98SLois Curfman McInnes {
606a935fc98SLois Curfman McInnes   SNES       snes = (SNES)obj;
607a935fc98SLois Curfman McInnes   SNES_LS    *ls = (SNES_LS *)snes->data;
608d636dbe3SBarry Smith   FILE       *fd;
60919bcc07fSBarry Smith   char       *cstr;
61051695f54SLois Curfman McInnes   int        ierr;
61119bcc07fSBarry Smith   ViewerType vtype;
612a935fc98SLois Curfman McInnes 
6133a40ed3dSBarry Smith   PetscFunctionBegin;
61419bcc07fSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
61519bcc07fSBarry Smith   if (vtype  == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
61690ace30eSBarry Smith     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
61719bcc07fSBarry Smith     if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch";
61819bcc07fSBarry Smith     else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch";
61919bcc07fSBarry Smith     else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch";
62019bcc07fSBarry Smith     else cstr = "unknown";
62177c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    line search variant: %s\n",cstr);
62277c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    alpha=%g, maxstep=%g, steptol=%g\n",
623a935fc98SLois Curfman McInnes                  ls->alpha,ls->maxstep,ls->steptol);
62419bcc07fSBarry Smith   }
6253a40ed3dSBarry Smith   PetscFunctionReturn(0);
626a935fc98SLois Curfman McInnes }
62752392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6285615d1e5SSatish Balay #undef __FUNC__
6295615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS"
630f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes)
6315e42470aSBarry Smith {
6325e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
6335e42470aSBarry Smith   char    ver[16];
6345e42470aSBarry Smith   double  tmp;
63525cdf11fSBarry Smith   int     ierr,flg;
6365e42470aSBarry Smith 
6373a40ed3dSBarry Smith   PetscFunctionBegin;
63809d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr);
63925cdf11fSBarry Smith   if (flg) {
6405e42470aSBarry Smith     ls->alpha = tmp;
6415e42470aSBarry Smith   }
64209d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr);
64325cdf11fSBarry Smith   if (flg) {
6445e42470aSBarry Smith     ls->maxstep = tmp;
6455e42470aSBarry Smith   }
64609d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr);
64725cdf11fSBarry Smith   if (flg) {
6485e42470aSBarry Smith     ls->steptol = tmp;
6495e42470aSBarry Smith   }
65009d61ba7SLois Curfman McInnes   ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr);
65125cdf11fSBarry Smith   if (flg) {
65248d91487SBarry Smith     if (!PetscStrcmp(ver,"basic")) {
65377c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearch);
6545e42470aSBarry Smith     }
65529e0b56fSBarry Smith     else if (!PetscStrcmp(ver,"basicnonorms")) {
65629e0b56fSBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearchNoNorms);
65729e0b56fSBarry Smith     }
65848d91487SBarry Smith     else if (!PetscStrcmp(ver,"quadratic")) {
65977c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESQuadraticLineSearch);
6605e42470aSBarry Smith     }
66148d91487SBarry Smith     else if (!PetscStrcmp(ver,"cubic")) {
66277c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESCubicLineSearch);
6635e42470aSBarry Smith     }
664a8c6a408SBarry Smith     else {SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown line search");}
6655e42470aSBarry Smith   }
6663a40ed3dSBarry Smith   PetscFunctionReturn(0);
6675e42470aSBarry Smith }
6685e42470aSBarry Smith /* ------------------------------------------------------------ */
6695615d1e5SSatish Balay #undef __FUNC__
6705615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS"
671f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES  snes )
6725e42470aSBarry Smith {
6735e42470aSBarry Smith   SNES_LS *neP;
6745e42470aSBarry Smith 
6753a40ed3dSBarry Smith   PetscFunctionBegin;
676a8c6a408SBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
677a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only");
678a8c6a408SBarry Smith   }
679f63b844aSLois Curfman McInnes   snes->type		= SNES_EQ_LS;
680f63b844aSLois Curfman McInnes   snes->setup		= SNESSetUp_EQ_LS;
681f63b844aSLois Curfman McInnes   snes->solve		= SNESSolve_EQ_LS;
682f63b844aSLois Curfman McInnes   snes->destroy		= SNESDestroy_EQ_LS;
683f63b844aSLois Curfman McInnes   snes->converged	= SNESConverged_EQ_LS;
684f63b844aSLois Curfman McInnes   snes->printhelp       = SNESPrintHelp_EQ_LS;
685f63b844aSLois Curfman McInnes   snes->setfromoptions  = SNESSetFromOptions_EQ_LS;
686f63b844aSLois Curfman McInnes   snes->view            = SNESView_EQ_LS;
6875baf8537SBarry Smith   snes->nwork           = 0;
6885e42470aSBarry Smith 
6890452661fSBarry Smith   neP			= PetscNew(SNES_LS);   CHKPTRQ(neP);
690ff782a9fSLois Curfman McInnes   PLogObjectMemory(snes,sizeof(SNES_LS));
6915e42470aSBarry Smith   snes->data    	= (void *) neP;
6925e42470aSBarry Smith   neP->alpha		= 1.e-4;
6935e42470aSBarry Smith   neP->maxstep		= 1.e8;
6945e42470aSBarry Smith   neP->steptol		= 1.e-12;
6955e42470aSBarry Smith   neP->LineSearch       = SNESCubicLineSearch;
6963a40ed3dSBarry Smith   PetscFunctionReturn(0);
6975e42470aSBarry Smith }
6985e42470aSBarry Smith 
699