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