xref: /petsc/src/snes/impls/ls/ls.c (revision fee21e364a2af8f69c0e7984443fdef19f844ae9)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*fee21e36SBarry Smith static char vcid[] = "$Id: ls.c,v 1.104 1998/04/09 04:18:17 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"
124e1311b90SBarry 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 
159*fee21e36SBarry Smith    Collective on SNES and Vec
160*fee21e36SBarry Smith 
161c4a48953SLois Curfman McInnes    Options Database Key:
16209d61ba7SLois Curfman McInnes $  -snes_eq_ls basic
163c4a48953SLois Curfman McInnes 
16428ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
16528ae5a21SLois Curfman McInnes 
166f59ffdedSLois Curfman McInnes .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
16777c4ece6SBarry Smith           SNESSetLineSearch()
1685e76c431SBarry Smith @*/
1695e42470aSBarry Smith int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
170761aaf1bSLois Curfman McInnes                      double fnorm, double *ynorm, double *gnorm,int *flag )
1715e76c431SBarry Smith {
1725e42470aSBarry Smith   int    ierr;
1735334005bSBarry Smith   Scalar mone = -1.0;
1745334005bSBarry Smith 
1753a40ed3dSBarry Smith   PetscFunctionBegin;
176761aaf1bSLois Curfman McInnes   *flag = 0;
1777857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
178cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);       /* ynorm = || y || */
179ea4d3ed3SLois Curfman McInnes   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
180ea4d3ed3SLois Curfman McInnes   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
181cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);       /* gnorm = || g || */
1827857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
1833a40ed3dSBarry Smith   PetscFunctionReturn(0);
1845e76c431SBarry Smith }
1855e76c431SBarry Smith /* ------------------------------------------------------------------ */
1865615d1e5SSatish Balay #undef __FUNC__
18729e0b56fSBarry Smith #define __FUNC__ "SNESNoLineSearchNoNorms"
18882bf6240SBarry Smith 
18929e0b56fSBarry Smith /*@C
19029e0b56fSBarry Smith    SNESNoLineSearchNoNorms - This routine is not a line search at
19129e0b56fSBarry Smith    all; it simply uses the full Newton step. This version does not
19229e0b56fSBarry Smith    even compute the norm of the function or search direction; this
19329e0b56fSBarry Smith    is intended only when you know the full step is fine and are
19429e0b56fSBarry Smith    not checking for convergence of the nonlinear iteration (for
19529e0b56fSBarry Smith    example, you are running always for a fixed number of Newton
19629e0b56fSBarry Smith    steps).
19729e0b56fSBarry Smith 
19829e0b56fSBarry Smith    Input Parameters:
19929e0b56fSBarry Smith .  snes - nonlinear context
20029e0b56fSBarry Smith .  x - current iterate
20129e0b56fSBarry Smith .  f - residual evaluated at x
20229e0b56fSBarry Smith .  y - search direction (contains new iterate on output)
20329e0b56fSBarry Smith .  w - work vector
20429e0b56fSBarry Smith .  fnorm - 2-norm of f
20529e0b56fSBarry Smith 
20629e0b56fSBarry Smith    Output Parameters:
20729e0b56fSBarry Smith .  g - residual evaluated at new iterate y
20829e0b56fSBarry Smith .  gnorm - not changed
20929e0b56fSBarry Smith .  ynorm - not changed
21029e0b56fSBarry Smith .  flag - set to 0, indicating a successful line search
21129e0b56fSBarry Smith 
212*fee21e36SBarry Smith    Collective on SNES and Vec
213*fee21e36SBarry Smith 
21429e0b56fSBarry Smith    Options Database Key:
21529e0b56fSBarry Smith $  -snes_eq_ls basicnonorms
21629e0b56fSBarry Smith 
21729e0b56fSBarry Smith .keywords: SNES, nonlinear, line search, cubic
21829e0b56fSBarry Smith 
21929e0b56fSBarry Smith .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(),
22029e0b56fSBarry Smith           SNESSetLineSearch(), SNESNoLineSearch()
22129e0b56fSBarry Smith @*/
22229e0b56fSBarry Smith int SNESNoLineSearchNoNorms(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
22329e0b56fSBarry Smith                      double fnorm, double *ynorm, double *gnorm,int *flag )
22429e0b56fSBarry Smith {
22529e0b56fSBarry Smith   int    ierr;
22629e0b56fSBarry Smith   Scalar mone = -1.0;
22729e0b56fSBarry Smith 
2283a40ed3dSBarry Smith   PetscFunctionBegin;
22929e0b56fSBarry Smith   *flag = 0;
23029e0b56fSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
23129e0b56fSBarry Smith   ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr);            /* y <- y - x      */
23229e0b56fSBarry Smith   ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y)    */
23329e0b56fSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
2343a40ed3dSBarry Smith   PetscFunctionReturn(0);
23529e0b56fSBarry Smith }
23629e0b56fSBarry Smith /* ------------------------------------------------------------------ */
23729e0b56fSBarry Smith #undef __FUNC__
2385615d1e5SSatish Balay #define __FUNC__ "SNESCubicLineSearch"
2394b828684SBarry Smith /*@C
240f525115eSLois Curfman McInnes    SNESCubicLineSearch - Performs a cubic line search (default line search method).
2415e76c431SBarry Smith 
2425e76c431SBarry Smith    Input Parameters:
2435e42470aSBarry Smith .  snes - nonlinear context
2445e76c431SBarry Smith .  x - current iterate
2455e76c431SBarry Smith .  f - residual evaluated at x
2465e76c431SBarry Smith .  y - search direction (contains new iterate on output)
2475e76c431SBarry Smith .  w - work vector
2485e76c431SBarry Smith .  fnorm - 2-norm of f
2495e76c431SBarry Smith 
250393d2d9aSLois Curfman McInnes    Output Parameters:
2515e76c431SBarry Smith .  g - residual evaluated at new iterate y
2525e76c431SBarry Smith .  y - new iterate (contains search direction on input)
2535e76c431SBarry Smith .  gnorm - 2-norm of g
2545e76c431SBarry Smith .  ynorm - 2-norm of search length
255761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
2565e76c431SBarry Smith 
257*fee21e36SBarry Smith    Collective on SNES
258*fee21e36SBarry Smith 
259c4a48953SLois Curfman McInnes    Options Database Key:
26009d61ba7SLois Curfman McInnes $  -snes_eq_ls cubic
261c4a48953SLois Curfman McInnes 
2625e76c431SBarry Smith    Notes:
2635e76c431SBarry Smith    This line search is taken from "Numerical Methods for Unconstrained
2645e76c431SBarry Smith    Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325.
2655e76c431SBarry Smith 
26628ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic
26728ae5a21SLois Curfman McInnes 
26877c4ece6SBarry Smith .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
2695e76c431SBarry Smith @*/
2705e42470aSBarry Smith int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w,
271761aaf1bSLois Curfman McInnes                         double fnorm,double *ynorm,double *gnorm,int *flag)
2725e76c431SBarry Smith {
273406556e6SLois Curfman McInnes   /*
274406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
275406556e6SLois Curfman McInnes      minimization problem:
276406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
277406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
278406556e6SLois Curfman McInnes    */
279406556e6SLois Curfman McInnes 
280ddd12767SBarry Smith   double  steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2;
281ea4d3ed3SLois Curfman McInnes   double  maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg;
2823a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
2835e42470aSBarry Smith   Scalar  cinitslope, clambda;
2846b5873e3SBarry Smith #endif
2855e42470aSBarry Smith   int     ierr, count;
2865e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
2875334005bSBarry Smith   Scalar  mone = -1.0,scale;
2885e76c431SBarry Smith 
2893a40ed3dSBarry Smith   PetscFunctionBegin;
2907857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
291761aaf1bSLois Curfman McInnes   *flag   = 0;
2925e76c431SBarry Smith   alpha   = neP->alpha;
2935e76c431SBarry Smith   maxstep = neP->maxstep;
2945e76c431SBarry Smith   steptol = neP->steptol;
2955e76c431SBarry Smith 
296cddf8d76SBarry Smith   ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr);
297a1c2b6eeSLois Curfman McInnes   if (*ynorm < snes->atol) {
298a1c2b6eeSLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Search direction and size are nearly 0\n");
299a1c2b6eeSLois Curfman McInnes     *gnorm = fnorm;
300a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
301a1c2b6eeSLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
302ad922ac9SBarry Smith     goto theend1;
30394a9d846SBarry Smith   }
3045e76c431SBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
3055e42470aSBarry Smith     scale = maxstep/(*ynorm);
3063a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
30794a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale));
3086b5873e3SBarry Smith #else
30994a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale);
3106b5873e3SBarry Smith #endif
311393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
3125e76c431SBarry Smith     *ynorm = maxstep;
3135e76c431SBarry Smith   }
3145e76c431SBarry Smith   minlambda = steptol/(*ynorm);
315a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
3163a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
317a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
3185e42470aSBarry Smith   initslope = real(cinitslope);
3195e42470aSBarry Smith #else
320a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
3215e42470aSBarry Smith #endif
3225e76c431SBarry Smith   if (initslope > 0.0) initslope = -initslope;
3235e76c431SBarry Smith   if (initslope == 0.0) initslope = -1.0;
3245e76c431SBarry Smith 
325393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
3265334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
32778b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
328cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm);
329406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
330393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
33194a424c1SBarry Smith     PLogInfo(snes,"SNESCubicLineSearch: Using full step\n");
332ad922ac9SBarry Smith     goto theend1;
3335e76c431SBarry Smith   }
3345e76c431SBarry Smith 
3355e76c431SBarry Smith   /* Fit points with quadratic */
3365e76c431SBarry Smith   lambda = 1.0; count = 0;
337a703fe33SLois Curfman McInnes   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
3385e76c431SBarry Smith   lambdaprev = lambda;
3395e76c431SBarry Smith   gnormprev = *gnorm;
340ddd12767SBarry Smith   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
341ddd12767SBarry Smith   else lambda = lambdatemp;
342393d2d9aSLois Curfman McInnes   ierr   = VecCopy(x,w); CHKERRQ(ierr);
343ea4d3ed3SLois Curfman McInnes   lambdaneg = -lambda;
3443a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
345ea4d3ed3SLois Curfman McInnes   clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3465e42470aSBarry Smith #else
347ea4d3ed3SLois Curfman McInnes   ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3485e42470aSBarry Smith #endif
34978b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
350cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
351406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
352393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
353ea4d3ed3SLois Curfman McInnes     PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda);
354ad922ac9SBarry Smith     goto theend1;
3555e76c431SBarry Smith   }
3565e76c431SBarry Smith 
3575e76c431SBarry Smith   /* Fit points with cubic */
3585e76c431SBarry Smith   count = 1;
3595e76c431SBarry Smith   while (1) {
3605e76c431SBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
3612b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:Unable to find good step length! %d \n",count);
3622b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
363ea4d3ed3SLois Curfman McInnes                fnorm,*gnorm,*ynorm,lambda,initslope);
364393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
365761aaf1bSLois Curfman McInnes       *flag = -1; break;
3665e76c431SBarry Smith     }
367406556e6SLois Curfman McInnes     t1 = ((*gnorm)*(*gnorm) - fnorm*fnorm)*0.5 - lambda*initslope;
368406556e6SLois Curfman McInnes     t2 = (gnormprev*gnormprev  - fnorm*fnorm)*0.5 - lambdaprev*initslope;
369ddd12767SBarry Smith     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3702b022350SLois Curfman McInnes     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
3715e76c431SBarry Smith     d  = b*b - 3*a*initslope;
3725e76c431SBarry Smith     if (d < 0.0) d = 0.0;
3735e76c431SBarry Smith     if (a == 0.0) {
3745e76c431SBarry Smith       lambdatemp = -initslope/(2.0*b);
3755e76c431SBarry Smith     } else {
3765e76c431SBarry Smith       lambdatemp = (-b + sqrt(d))/(3.0*a);
3775e76c431SBarry Smith     }
3785e76c431SBarry Smith     if (lambdatemp > .5*lambda) {
3795e76c431SBarry Smith       lambdatemp = .5*lambda;
3805e76c431SBarry Smith     }
3815e76c431SBarry Smith     lambdaprev = lambda;
3825e76c431SBarry Smith     gnormprev = *gnorm;
3835e76c431SBarry Smith     if (lambdatemp <= .1*lambda) {
3845e76c431SBarry Smith       lambda = .1*lambda;
3855e76c431SBarry Smith     }
3865e76c431SBarry Smith     else lambda = lambdatemp;
387393d2d9aSLois Curfman McInnes     ierr = VecCopy( x, w ); CHKERRQ(ierr);
388ea4d3ed3SLois Curfman McInnes     lambdaneg = -lambda;
3893a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
390ea4d3ed3SLois Curfman McInnes     clambda = lambdaneg;
391393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
3925e42470aSBarry Smith #else
393ea4d3ed3SLois Curfman McInnes     ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr);
3945e42470aSBarry Smith #endif
39578b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
396cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
397406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* is reduction enough? */
398393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
399ea4d3ed3SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda);
4002715565aSLois Curfman McInnes       goto theend1;
4012b022350SLois Curfman McInnes     } else {
4022b022350SLois Curfman McInnes       PLogInfo(snes,"SNESCubicLineSearch: Cubic step no good, shrinking lambda,  lambda=%g\n",lambda);
4035e76c431SBarry Smith     }
4045e76c431SBarry Smith     count++;
4055e76c431SBarry Smith   }
406ad922ac9SBarry Smith   theend1:
4077857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
4083a40ed3dSBarry Smith   PetscFunctionReturn(0);
4095e76c431SBarry Smith }
41052392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
4115615d1e5SSatish Balay #undef __FUNC__
4125615d1e5SSatish Balay #define __FUNC__ "SNESQuadraticLineSearch"
4134b828684SBarry Smith /*@C
414f525115eSLois Curfman McInnes    SNESQuadraticLineSearch - Performs a quadratic line search.
4155e76c431SBarry Smith 
4165e42470aSBarry Smith    Input Parameters:
417f59ffdedSLois Curfman McInnes .  snes - the SNES context
4185e42470aSBarry Smith .  x - current iterate
4195e42470aSBarry Smith .  f - residual evaluated at x
4205e42470aSBarry Smith .  y - search direction (contains new iterate on output)
4215e42470aSBarry Smith .  w - work vector
4225e42470aSBarry Smith .  fnorm - 2-norm of f
4235e42470aSBarry Smith 
424c4a48953SLois Curfman McInnes    Output Parameters:
4255e42470aSBarry Smith .  g - residual evaluated at new iterate y
4265e42470aSBarry Smith .  y - new iterate (contains search direction on input)
4275e42470aSBarry Smith .  gnorm - 2-norm of g
4285e42470aSBarry Smith .  ynorm - 2-norm of search length
429761aaf1bSLois Curfman McInnes .  flag - 0 if line search succeeds; -1 on failure.
4305e42470aSBarry Smith 
431*fee21e36SBarry Smith    Collective on SNES and Vec
432*fee21e36SBarry Smith 
433c4a48953SLois Curfman McInnes    Options Database Key:
43409d61ba7SLois Curfman McInnes $  -snes_eq_ls quadratic
435c4a48953SLois Curfman McInnes 
4365e42470aSBarry Smith    Notes:
43777c4ece6SBarry Smith    Use SNESSetLineSearch()
438f63b844aSLois Curfman McInnes    to set this routine within the SNES_EQ_LS method.
4395e42470aSBarry Smith 
440f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, quadratic, line search
441f59ffdedSLois Curfman McInnes 
44277c4ece6SBarry Smith .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch()
4435e42470aSBarry Smith @*/
4445e42470aSBarry Smith int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w,
445761aaf1bSLois Curfman McInnes                            double fnorm, double *ynorm, double *gnorm,int *flag)
4465e76c431SBarry Smith {
447406556e6SLois Curfman McInnes   /*
448406556e6SLois Curfman McInnes      Note that for line search purposes we work with with the related
449406556e6SLois Curfman McInnes      minimization problem:
450406556e6SLois Curfman McInnes         min  z(x):  R^n -> R,
451406556e6SLois Curfman McInnes      where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2.
452406556e6SLois Curfman McInnes    */
45340011551SBarry Smith   double  steptol,initslope,maxstep,minlambda,alpha,lambda,lambdatemp;
4543a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
4555e42470aSBarry Smith   Scalar  cinitslope,clambda;
4566b5873e3SBarry Smith #endif
4575e42470aSBarry Smith   int     ierr,count;
4585e42470aSBarry Smith   SNES_LS *neP = (SNES_LS *) snes->data;
4595334005bSBarry Smith   Scalar  mone = -1.0,scale;
4605e76c431SBarry Smith 
4613a40ed3dSBarry Smith   PetscFunctionBegin;
4627857610eSBarry Smith   PLogEventBegin(SNES_LineSearch,snes,x,f,g);
463761aaf1bSLois Curfman McInnes   *flag   = 0;
4645e42470aSBarry Smith   alpha   = neP->alpha;
4655e42470aSBarry Smith   maxstep = neP->maxstep;
4665e42470aSBarry Smith   steptol = neP->steptol;
4675e76c431SBarry Smith 
468cddf8d76SBarry Smith   VecNorm(y, NORM_2,ynorm );
469b37302c6SLois Curfman McInnes   if (*ynorm < snes->atol) {
47094a9d846SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n");
471b37302c6SLois Curfman McInnes     *gnorm = fnorm;
472b37302c6SLois Curfman McInnes     ierr = VecCopy(x,y); CHKERRQ(ierr);
473b37302c6SLois Curfman McInnes     ierr = VecCopy(f,g); CHKERRQ(ierr);
474ad922ac9SBarry Smith     goto theend2;
47594a9d846SBarry Smith   }
4765e42470aSBarry Smith   if (*ynorm > maxstep) {	/* Step too big, so scale back */
4775e42470aSBarry Smith     scale = maxstep/(*ynorm);
478393d2d9aSLois Curfman McInnes     ierr = VecScale(&scale,y); CHKERRQ(ierr);
4795e42470aSBarry Smith     *ynorm = maxstep;
4805e76c431SBarry Smith   }
4815e42470aSBarry Smith   minlambda = steptol/(*ynorm);
482a703fe33SLois Curfman McInnes   ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr);
4833a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
484a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr);
4855e42470aSBarry Smith   initslope = real(cinitslope);
4865e42470aSBarry Smith #else
487a703fe33SLois Curfman McInnes   ierr = VecDot(f,w,&initslope); CHKERRQ(ierr);
4885e42470aSBarry Smith #endif
4895e42470aSBarry Smith   if (initslope > 0.0) initslope = -initslope;
4905e42470aSBarry Smith   if (initslope == 0.0) initslope = -1.0;
4915e42470aSBarry Smith 
492393d2d9aSLois Curfman McInnes   ierr = VecCopy(y,w); CHKERRQ(ierr);
4935334005bSBarry Smith   ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr);
49478b31e54SBarry Smith   ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
495cddf8d76SBarry Smith   ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
496406556e6SLois Curfman McInnes   if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */
497393d2d9aSLois Curfman McInnes     ierr = VecCopy(w,y); CHKERRQ(ierr);
49894a424c1SBarry Smith     PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n");
499ad922ac9SBarry Smith     goto theend2;
5005e42470aSBarry Smith   }
5015e42470aSBarry Smith 
5025e42470aSBarry Smith   /* Fit points with quadratic */
5035e42470aSBarry Smith   lambda = 1.0; count = 0;
5045e42470aSBarry Smith   count = 1;
5055e42470aSBarry Smith   while (1) {
5065e42470aSBarry Smith     if (lambda <= minlambda) { /* bad luck; use full step */
507981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:Unable to find good step length! %d \n",count);
508981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",
509ea4d3ed3SLois Curfman McInnes                fnorm,*gnorm,*ynorm,lambda,initslope);
510393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
511761aaf1bSLois Curfman McInnes       *flag = -1; break;
5125e42470aSBarry Smith     }
513a703fe33SLois Curfman McInnes     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
5145e42470aSBarry Smith     if (lambdatemp <= .1*lambda) {
5155e42470aSBarry Smith       lambda = .1*lambda;
5165e42470aSBarry Smith     } else lambda = lambdatemp;
517393d2d9aSLois Curfman McInnes     ierr = VecCopy(x,w); CHKERRQ(ierr);
5185334005bSBarry Smith     lambda = -lambda;
5193a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
520393d2d9aSLois Curfman McInnes     clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr);
5215e42470aSBarry Smith #else
522393d2d9aSLois Curfman McInnes     ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr);
5235e42470aSBarry Smith #endif
52478b31e54SBarry Smith     ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr);
525cddf8d76SBarry Smith     ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr);
526406556e6SLois Curfman McInnes     if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */
527393d2d9aSLois Curfman McInnes       ierr = VecCopy(w,y); CHKERRQ(ierr);
528981c4779SBarry Smith       PLogInfo(snes,"SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda);
52906259719SBarry Smith       break;
5305e42470aSBarry Smith     }
5315e42470aSBarry Smith     count++;
5325e42470aSBarry Smith   }
533ad922ac9SBarry Smith   theend2:
5347857610eSBarry Smith   PLogEventEnd(SNES_LineSearch,snes,x,f,g);
5353a40ed3dSBarry Smith   PetscFunctionReturn(0);
5365e76c431SBarry Smith }
53782bf6240SBarry Smith 
5385e76c431SBarry Smith /* ------------------------------------------------------------ */
5395615d1e5SSatish Balay #undef __FUNC__
540d4bb536fSBarry Smith #define __FUNC__ "SNESSetLineSearch"
541c9e6a524SLois Curfman McInnes /*@C
54277c4ece6SBarry Smith    SNESSetLineSearch - Sets the line search routine to be used
543f63b844aSLois Curfman McInnes    by the method SNES_EQ_LS.
5445e76c431SBarry Smith 
5455e76c431SBarry Smith    Input Parameters:
546eafb4bcbSBarry Smith .  snes - nonlinear context obtained from SNESCreate()
5475e76c431SBarry Smith .  func - pointer to int function
5485e76c431SBarry Smith 
549*fee21e36SBarry Smith    Collective on SNES
550*fee21e36SBarry Smith 
551c4a48953SLois Curfman McInnes    Available Routines:
552f59ffdedSLois Curfman McInnes .  SNESCubicLineSearch() - default line search
553f59ffdedSLois Curfman McInnes .  SNESQuadraticLineSearch() - quadratic line search
554f59ffdedSLois Curfman McInnes .  SNESNoLineSearch() - the full Newton step (actually not a line search)
55582bf6240SBarry Smith .  SNESNoLineSearchNoNorms() - use the full Newton step (calculate no norms; faster in parallel)
5565e76c431SBarry Smith 
557c4a48953SLois Curfman McInnes     Options Database Keys:
55809d61ba7SLois Curfman McInnes $   -snes_eq_ls [basic,quadratic,cubic]
559912ebf9aSLois Curfman McInnes $   -snes_eq_ls_alpha <alpha>
560912ebf9aSLois Curfman McInnes $   -snes_eq_ls_maxstep <max>
561912ebf9aSLois Curfman McInnes $   -snes_eq_ls_steptol <steptol>
562c4a48953SLois Curfman McInnes 
5635e76c431SBarry Smith    Calling sequence of func:
564f59ffdedSLois Curfman McInnes    func (SNES snes, Vec x, Vec f, Vec g, Vec y,
565761aaf1bSLois Curfman McInnes          Vec w, double fnorm, double *ynorm,
566761aaf1bSLois Curfman McInnes          double *gnorm, *flag)
5675e76c431SBarry Smith 
5685e76c431SBarry Smith     Input parameters for func:
5695e42470aSBarry Smith .   snes - nonlinear context
5705e76c431SBarry Smith .   x - current iterate
5715e76c431SBarry Smith .   f - residual evaluated at x
5725e76c431SBarry Smith .   y - search direction (contains new iterate on output)
5735e76c431SBarry Smith .   w - work vector
5745e76c431SBarry Smith .   fnorm - 2-norm of f
5755e76c431SBarry Smith 
5765e76c431SBarry Smith     Output parameters for func:
5775e76c431SBarry Smith .   g - residual evaluated at new iterate y
5785e76c431SBarry Smith .   y - new iterate (contains search direction on input)
5795e76c431SBarry Smith .   gnorm - 2-norm of g
5805e76c431SBarry Smith .   ynorm - 2-norm of search length
581761aaf1bSLois Curfman McInnes .   flag - set to 0 if the line search succeeds; a nonzero integer
582761aaf1bSLois Curfman McInnes            on failure.
583f59ffdedSLois Curfman McInnes 
584f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, set, line search, routine
585f59ffdedSLois Curfman McInnes 
586f59ffdedSLois Curfman McInnes .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch()
5875e76c431SBarry Smith @*/
58877c4ece6SBarry Smith int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec,
589761aaf1bSLois Curfman McInnes                              double,double*,double*,int*))
5905e76c431SBarry Smith {
59182bf6240SBarry Smith   int ierr, (*f)(SNES,int (*f)(SNES,Vec,Vec,Vec,Vec,Vec,double,double*,double*,int*));
59282bf6240SBarry Smith 
5933a40ed3dSBarry Smith   PetscFunctionBegin;
594e1311b90SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESSetLineSearch",(void **)&f);CHKERRQ(ierr);
59582bf6240SBarry Smith   if (f) {
59682bf6240SBarry Smith     ierr = (*f)(snes,func);CHKERRQ(ierr);
59782bf6240SBarry Smith   }
5983a40ed3dSBarry Smith   PetscFunctionReturn(0);
5995e76c431SBarry Smith }
60082bf6240SBarry Smith 
60182bf6240SBarry Smith #undef __FUNC__
60282bf6240SBarry Smith #define __FUNC__ "SNESSetLineSearch_LS"
60382bf6240SBarry Smith int SNESSetLineSearch_LS(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec,
60482bf6240SBarry Smith                          double,double*,double*,int*))
60582bf6240SBarry Smith {
60682bf6240SBarry Smith   PetscFunctionBegin;
60782bf6240SBarry Smith   ((SNES_LS *)(snes->data))->LineSearch = func;
60882bf6240SBarry Smith   PetscFunctionReturn(0);
60982bf6240SBarry Smith }
61082bf6240SBarry Smith 
61152392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6125615d1e5SSatish Balay #undef __FUNC__
613d4bb536fSBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS"
614f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p)
6155e42470aSBarry Smith {
6165e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
6176daaf66cSBarry Smith 
6183a40ed3dSBarry Smith   PetscFunctionBegin;
61976be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n");
62076be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls [basic,quadratic,cubic]\n",p);
62176be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha);
62276be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep);
62376be9ce4SBarry Smith   (*PetscHelpPrintf)(snes->comm,"   %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol);
6243a40ed3dSBarry Smith   PetscFunctionReturn(0);
6255e42470aSBarry Smith }
62652392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6275615d1e5SSatish Balay #undef __FUNC__
628d4bb536fSBarry Smith #define __FUNC__ "SNESView_EQ_LS"
629e1311b90SBarry Smith static int SNESView_EQ_LS(SNES snes,Viewer viewer)
630a935fc98SLois Curfman McInnes {
631a935fc98SLois Curfman McInnes   SNES_LS    *ls = (SNES_LS *)snes->data;
632d636dbe3SBarry Smith   FILE       *fd;
63319bcc07fSBarry Smith   char       *cstr;
63451695f54SLois Curfman McInnes   int        ierr;
63519bcc07fSBarry Smith   ViewerType vtype;
636a935fc98SLois Curfman McInnes 
6373a40ed3dSBarry Smith   PetscFunctionBegin;
63819bcc07fSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
63919bcc07fSBarry Smith   if (vtype  == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
64090ace30eSBarry Smith     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
64119bcc07fSBarry Smith     if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch";
64219bcc07fSBarry Smith     else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch";
64319bcc07fSBarry Smith     else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch";
64419bcc07fSBarry Smith     else cstr = "unknown";
64577c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    line search variant: %s\n",cstr);
64677c4ece6SBarry Smith     PetscFPrintf(snes->comm,fd,"    alpha=%g, maxstep=%g, steptol=%g\n",
647a935fc98SLois Curfman McInnes                  ls->alpha,ls->maxstep,ls->steptol);
6485cd90555SBarry Smith   } else {
6495cd90555SBarry Smith     SETERRQ(1,1,"Viewer type not supported for this object");
65019bcc07fSBarry Smith   }
6513a40ed3dSBarry Smith   PetscFunctionReturn(0);
652a935fc98SLois Curfman McInnes }
65352392280SLois Curfman McInnes /* ------------------------------------------------------------------ */
6545615d1e5SSatish Balay #undef __FUNC__
6555615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS"
656f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes)
6575e42470aSBarry Smith {
6585e42470aSBarry Smith   SNES_LS *ls = (SNES_LS *)snes->data;
6595e42470aSBarry Smith   char    ver[16];
6605e42470aSBarry Smith   double  tmp;
66125cdf11fSBarry Smith   int     ierr,flg;
6625e42470aSBarry Smith 
6633a40ed3dSBarry Smith   PetscFunctionBegin;
66409d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr);
66525cdf11fSBarry Smith   if (flg) {
6665e42470aSBarry Smith     ls->alpha = tmp;
6675e42470aSBarry Smith   }
66809d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr);
66925cdf11fSBarry Smith   if (flg) {
6705e42470aSBarry Smith     ls->maxstep = tmp;
6715e42470aSBarry Smith   }
67209d61ba7SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr);
67325cdf11fSBarry Smith   if (flg) {
6745e42470aSBarry Smith     ls->steptol = tmp;
6755e42470aSBarry Smith   }
67609d61ba7SLois Curfman McInnes   ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr);
67725cdf11fSBarry Smith   if (flg) {
67848d91487SBarry Smith     if (!PetscStrcmp(ver,"basic")) {
67977c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearch);
6805e42470aSBarry Smith     }
68129e0b56fSBarry Smith     else if (!PetscStrcmp(ver,"basicnonorms")) {
68229e0b56fSBarry Smith       SNESSetLineSearch(snes,SNESNoLineSearchNoNorms);
68329e0b56fSBarry Smith     }
68448d91487SBarry Smith     else if (!PetscStrcmp(ver,"quadratic")) {
68577c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESQuadraticLineSearch);
6865e42470aSBarry Smith     }
68748d91487SBarry Smith     else if (!PetscStrcmp(ver,"cubic")) {
68877c4ece6SBarry Smith       SNESSetLineSearch(snes,SNESCubicLineSearch);
6895e42470aSBarry Smith     }
690a8c6a408SBarry Smith     else {SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown line search");}
6915e42470aSBarry Smith   }
6923a40ed3dSBarry Smith   PetscFunctionReturn(0);
6935e42470aSBarry Smith }
6945e42470aSBarry Smith /* ------------------------------------------------------------ */
6955615d1e5SSatish Balay #undef __FUNC__
6965615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS"
697f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES  snes )
6985e42470aSBarry Smith {
69982bf6240SBarry Smith   int     ierr;
7005e42470aSBarry Smith   SNES_LS *neP;
7015e42470aSBarry Smith 
7023a40ed3dSBarry Smith   PetscFunctionBegin;
703a8c6a408SBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
704a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only");
705a8c6a408SBarry Smith   }
70682bf6240SBarry Smith 
707f63b844aSLois Curfman McInnes   snes->setup		= SNESSetUp_EQ_LS;
708f63b844aSLois Curfman McInnes   snes->solve		= SNESSolve_EQ_LS;
709f63b844aSLois Curfman McInnes   snes->destroy		= SNESDestroy_EQ_LS;
710f63b844aSLois Curfman McInnes   snes->converged	= SNESConverged_EQ_LS;
711f63b844aSLois Curfman McInnes   snes->printhelp       = SNESPrintHelp_EQ_LS;
712f63b844aSLois Curfman McInnes   snes->setfromoptions  = SNESSetFromOptions_EQ_LS;
713f63b844aSLois Curfman McInnes   snes->view            = SNESView_EQ_LS;
7145baf8537SBarry Smith   snes->nwork           = 0;
7155e42470aSBarry Smith 
7160452661fSBarry Smith   neP			= PetscNew(SNES_LS);   CHKPTRQ(neP);
717ff782a9fSLois Curfman McInnes   PLogObjectMemory(snes,sizeof(SNES_LS));
7185e42470aSBarry Smith   snes->data    	= (void *) neP;
7195e42470aSBarry Smith   neP->alpha		= 1.e-4;
7205e42470aSBarry Smith   neP->maxstep		= 1.e8;
7215e42470aSBarry Smith   neP->steptol		= 1.e-12;
7225e42470aSBarry Smith   neP->LineSearch       = SNESCubicLineSearch;
72382bf6240SBarry Smith 
724e1311b90SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESSetLineSearch","SNESSetLineSearch_LS",
725e1311b90SBarry Smith                     (void*)SNESSetLineSearch_LS);CHKERRQ(ierr);
72682bf6240SBarry Smith 
7273a40ed3dSBarry Smith   PetscFunctionReturn(0);
7285e42470aSBarry Smith }
7295e42470aSBarry Smith 
73082bf6240SBarry Smith 
73182bf6240SBarry Smith 
73282bf6240SBarry Smith 
733