1*a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*a5eb4965SSatish Balay static char vcid[] = "$Id: ls.c,v 1.91 1997/06/12 21:49:20 bsmith Exp balay $"; 35e76c431SBarry Smith #endif 45e76c431SBarry Smith 55e76c431SBarry Smith #include <math.h> 670f55243SBarry Smith #include "src/snes/impls/ls/ls.h" 7b16a3bb1SBarry Smith #include "pinclude/pviewer.h" 85e42470aSBarry Smith 95e42470aSBarry Smith /* 105e42470aSBarry Smith Implements a line search variant of Newton's Method 115e76c431SBarry Smith for solving systems of nonlinear equations. 125e76c431SBarry Smith 135e76c431SBarry Smith Input parameters: 145e42470aSBarry Smith . snes - nonlinear context obtained from SNESCreate() 155e76c431SBarry Smith 165e42470aSBarry Smith Output Parameters: 17a935fc98SLois Curfman McInnes . outits - Number of global iterations until termination. 185e76c431SBarry Smith 195e76c431SBarry Smith Notes: 205e76c431SBarry Smith This implements essentially a truncated Newton method with a 215e76c431SBarry Smith line search. By default a cubic backtracking line search 225e76c431SBarry Smith is employed, as described in the text "Numerical Methods for 235e76c431SBarry Smith Unconstrained Optimization and Nonlinear Equations" by Dennis 24393d2d9aSLois Curfman McInnes and Schnabel. 255e76c431SBarry Smith */ 265e76c431SBarry Smith 275615d1e5SSatish Balay #undef __FUNC__ 285615d1e5SSatish Balay #define __FUNC__ "SNESSolve_EQ_LS" 29f63b844aSLois Curfman McInnes int SNESSolve_EQ_LS(SNES snes,int *outits) 305e76c431SBarry Smith { 315e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 32761aaf1bSLois Curfman McInnes int maxits, i, history_len, ierr, lits, lsfail; 33112a2221SBarry Smith MatStructure flg = DIFFERENT_NONZERO_PATTERN; 346b5873e3SBarry Smith double fnorm, gnorm, xnorm, ynorm, *history; 355e42470aSBarry Smith Vec Y, X, F, G, W, TMP; 365e76c431SBarry Smith 375e42470aSBarry Smith history = snes->conv_hist; /* convergence history */ 3851979daaSLois Curfman McInnes history_len = snes->conv_hist_size; /* convergence history length */ 395e42470aSBarry Smith maxits = snes->max_its; /* maximum number of iterations */ 405e42470aSBarry Smith X = snes->vec_sol; /* solution vector */ 4139e2f89bSBarry Smith F = snes->vec_func; /* residual vector */ 425e42470aSBarry Smith Y = snes->work[0]; /* work vectors */ 435e42470aSBarry Smith G = snes->work[1]; 445e42470aSBarry Smith W = snes->work[2]; 455e76c431SBarry Smith 4625ed9cd1SBarry Smith snes->iter = 0; 475334005bSBarry Smith ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr); /* F(X) */ 48cddf8d76SBarry Smith ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr); /* fnorm <- ||F|| */ 495e42470aSBarry Smith snes->norm = fnorm; 5051979daaSLois Curfman McInnes if (history) history[0] = fnorm; 5194a424c1SBarry Smith SNESMonitor(snes,0,fnorm); 525e76c431SBarry Smith 5394a9d846SBarry Smith if (fnorm == 0.0) {outits = 0; return 0;} 5494a9d846SBarry Smith 55d034289bSBarry Smith /* set parameter for default relative tolerance convergence test */ 56d034289bSBarry Smith snes->ttol = fnorm*snes->rtol; 57d034289bSBarry Smith 585e76c431SBarry Smith for ( i=0; i<maxits; i++ ) { 595e42470aSBarry Smith snes->iter = i+1; 605e76c431SBarry Smith 61ea4d3ed3SLois Curfman McInnes /* Solve J Y = F, where J is Jacobian matrix */ 625334005bSBarry Smith ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg); CHKERRQ(ierr); 635334005bSBarry Smith ierr = SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,flg); CHKERRQ(ierr); 6478b31e54SBarry Smith ierr = SLESSolve(snes->sles,F,Y,&lits); CHKERRQ(ierr); 657a00f4a9SLois Curfman McInnes snes->linear_its += PetscAbsInt(lits); 66af1ccdebSLois Curfman McInnes PLogInfo(snes,"SNESSolve_EQ_LS: iter=%d, linear solve iterations=%d\n",snes->iter,lits); 67ea4d3ed3SLois Curfman McInnes 68ea4d3ed3SLois Curfman McInnes /* Compute a (scaled) negative update in the line search routine: 69ea4d3ed3SLois Curfman McInnes Y <- X - lambda*Y 70ea4d3ed3SLois Curfman McInnes and evaluate G(Y) = function(Y)) 71ea4d3ed3SLois Curfman McInnes */ 7281b6cf68SLois Curfman McInnes ierr = VecCopy(Y,snes->vec_sol_update_always); CHKERRQ(ierr); 73ddd12767SBarry Smith ierr = (*neP->LineSearch)(snes,X,F,G,Y,W,fnorm,&ynorm,&gnorm,&lsfail); CHKERRQ(ierr); 74af1ccdebSLois Curfman McInnes PLogInfo(snes,"SNESSolve_EQ_LS: fnorm=%g, gnorm=%g, ynorm=%g, lsfail=%d\n",fnorm,gnorm,ynorm,lsfail); 75761aaf1bSLois Curfman McInnes if (lsfail) snes->nfailures++; 765e76c431SBarry Smith 7739e2f89bSBarry Smith TMP = F; F = G; snes->vec_func_always = F; G = TMP; 7839e2f89bSBarry Smith TMP = X; X = Y; snes->vec_sol_always = X; Y = TMP; 795e76c431SBarry Smith fnorm = gnorm; 805e76c431SBarry Smith 815e42470aSBarry Smith snes->norm = fnorm; 825e76c431SBarry Smith if (history && history_len > i+1) history[i+1] = fnorm; 8394a424c1SBarry Smith SNESMonitor(snes,i+1,fnorm); 845e76c431SBarry Smith 855e76c431SBarry Smith /* Test for convergence */ 8629e0b56fSBarry Smith if (snes->converged) { 8729e0b56fSBarry Smith ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr); /* xnorm = || X || */ 88bbb6d6a8SBarry Smith if ((*snes->converged)(snes,xnorm,ynorm,fnorm,snes->cnvP)) { 8916c95cacSBarry Smith break; 9016c95cacSBarry Smith } 9116c95cacSBarry Smith } 9229e0b56fSBarry Smith } 9339e2f89bSBarry Smith if (X != snes->vec_sol) { 94393d2d9aSLois Curfman McInnes ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr); 9539e2f89bSBarry Smith snes->vec_sol_always = snes->vec_sol; 9639e2f89bSBarry Smith snes->vec_func_always = snes->vec_func; 9739e2f89bSBarry Smith } 9852392280SLois Curfman McInnes if (i == maxits) { 9994a424c1SBarry Smith PLogInfo(snes, 100f63b844aSLois Curfman McInnes "SNESSolve_EQ_LS: Maximum number of iterations has been reached: %d\n",maxits); 10152392280SLois Curfman McInnes i--; 10252392280SLois Curfman McInnes } 10351979daaSLois Curfman McInnes if (history) snes->conv_act_size = (history_len < i+1) ? history_len : i+1; 1045e42470aSBarry Smith *outits = i+1; 1055e42470aSBarry Smith return 0; 1065e76c431SBarry Smith } 1075e76c431SBarry Smith /* ------------------------------------------------------------ */ 1085615d1e5SSatish Balay #undef __FUNC__ 1095615d1e5SSatish Balay #define __FUNC__ "SNESSetUp_EQ_LS" 110f63b844aSLois Curfman McInnes int SNESSetUp_EQ_LS(SNES snes ) 1115e76c431SBarry Smith { 1125e42470aSBarry Smith int ierr; 11381b6cf68SLois Curfman McInnes snes->nwork = 4; 114d7e8b826SBarry Smith ierr = VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);CHKERRQ(ierr); 1155e42470aSBarry Smith PLogObjectParents(snes,snes->nwork,snes->work); 11681b6cf68SLois Curfman McInnes snes->vec_sol_update_always = snes->work[3]; 1175e42470aSBarry Smith return 0; 1185e76c431SBarry Smith } 1195e76c431SBarry Smith /* ------------------------------------------------------------ */ 1205615d1e5SSatish Balay #undef __FUNC__ 1215eea60f9SBarry Smith #define __FUNC__ "SNESDestroy_EQ_LS" /* ADIC Ignore */ 122f63b844aSLois Curfman McInnes int SNESDestroy_EQ_LS(PetscObject obj) 1235e76c431SBarry Smith { 1245e42470aSBarry Smith SNES snes = (SNES) obj; 125393d2d9aSLois Curfman McInnes int ierr; 1265baf8537SBarry Smith if (snes->nwork) { 1274b0e389bSBarry Smith ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr); 12821c89e3eSBarry Smith } 1290452661fSBarry Smith PetscFree(snes->data); 1305e42470aSBarry Smith return 0; 1315e76c431SBarry Smith } 1325e76c431SBarry Smith /* ------------------------------------------------------------ */ 1335615d1e5SSatish Balay #undef __FUNC__ 1345615d1e5SSatish Balay #define __FUNC__ "SNESNoLineSearch" 1355e76c431SBarry Smith /*ARGSUSED*/ 1364b828684SBarry Smith /*@C 1375e42470aSBarry Smith SNESNoLineSearch - This routine is not a line search at all; 1385e76c431SBarry Smith it simply uses the full Newton step. Thus, this routine is intended 1395e76c431SBarry Smith to serve as a template and is not recommended for general use. 1405e76c431SBarry Smith 1415e76c431SBarry Smith Input Parameters: 1425e42470aSBarry Smith . snes - nonlinear context 1435e76c431SBarry Smith . x - current iterate 1445e76c431SBarry Smith . f - residual evaluated at x 1455e76c431SBarry Smith . y - search direction (contains new iterate on output) 1465e76c431SBarry Smith . w - work vector 1475e76c431SBarry Smith . fnorm - 2-norm of f 1485e76c431SBarry Smith 149c4a48953SLois Curfman McInnes Output Parameters: 1505e76c431SBarry Smith . g - residual evaluated at new iterate y 1515e76c431SBarry Smith . y - new iterate (contains search direction on input) 1525e76c431SBarry Smith . gnorm - 2-norm of g 1535e76c431SBarry Smith . ynorm - 2-norm of search length 154761aaf1bSLois Curfman McInnes . flag - set to 0, indicating a successful line search 1555e76c431SBarry Smith 156c4a48953SLois Curfman McInnes Options Database Key: 15709d61ba7SLois Curfman McInnes $ -snes_eq_ls basic 158c4a48953SLois Curfman McInnes 15928ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic 16028ae5a21SLois Curfman McInnes 161f59ffdedSLois Curfman McInnes .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(), 16277c4ece6SBarry Smith SNESSetLineSearch() 1635e76c431SBarry Smith @*/ 1645e42470aSBarry Smith int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 165761aaf1bSLois Curfman McInnes double fnorm, double *ynorm, double *gnorm,int *flag ) 1665e76c431SBarry Smith { 1675e42470aSBarry Smith int ierr; 1685334005bSBarry Smith Scalar mone = -1.0; 1695334005bSBarry Smith 170761aaf1bSLois Curfman McInnes *flag = 0; 1717857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 172cddf8d76SBarry Smith ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); /* ynorm = || y || */ 173ea4d3ed3SLois Curfman McInnes ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr); /* y <- y - x */ 174ea4d3ed3SLois Curfman McInnes ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y) */ 175cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); /* gnorm = || g || */ 1767857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 177761aaf1bSLois Curfman McInnes return 0; 1785e76c431SBarry Smith } 1795e76c431SBarry Smith /* ------------------------------------------------------------------ */ 1805615d1e5SSatish Balay #undef __FUNC__ 18129e0b56fSBarry Smith #define __FUNC__ "SNESNoLineSearchNoNorms" 18229e0b56fSBarry Smith /*ARGSUSED*/ 18329e0b56fSBarry Smith /*@C 18429e0b56fSBarry Smith SNESNoLineSearchNoNorms - This routine is not a line search at 18529e0b56fSBarry Smith all; it simply uses the full Newton step. This version does not 18629e0b56fSBarry Smith even compute the norm of the function or search direction; this 18729e0b56fSBarry Smith is intended only when you know the full step is fine and are 18829e0b56fSBarry Smith not checking for convergence of the nonlinear iteration (for 18929e0b56fSBarry Smith example, you are running always for a fixed number of Newton 19029e0b56fSBarry Smith steps). 19129e0b56fSBarry Smith 19229e0b56fSBarry Smith Input Parameters: 19329e0b56fSBarry Smith . snes - nonlinear context 19429e0b56fSBarry Smith . x - current iterate 19529e0b56fSBarry Smith . f - residual evaluated at x 19629e0b56fSBarry Smith . y - search direction (contains new iterate on output) 19729e0b56fSBarry Smith . w - work vector 19829e0b56fSBarry Smith . fnorm - 2-norm of f 19929e0b56fSBarry Smith 20029e0b56fSBarry Smith Output Parameters: 20129e0b56fSBarry Smith . g - residual evaluated at new iterate y 20229e0b56fSBarry Smith . gnorm - not changed 20329e0b56fSBarry Smith . ynorm - not changed 20429e0b56fSBarry Smith . flag - set to 0, indicating a successful line search 20529e0b56fSBarry Smith 20629e0b56fSBarry Smith Options Database Key: 20729e0b56fSBarry Smith $ -snes_eq_ls basicnonorms 20829e0b56fSBarry Smith 20929e0b56fSBarry Smith .keywords: SNES, nonlinear, line search, cubic 21029e0b56fSBarry Smith 21129e0b56fSBarry Smith .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(), 21229e0b56fSBarry Smith SNESSetLineSearch(), SNESNoLineSearch() 21329e0b56fSBarry Smith @*/ 21429e0b56fSBarry Smith int SNESNoLineSearchNoNorms(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 21529e0b56fSBarry Smith double fnorm, double *ynorm, double *gnorm,int *flag ) 21629e0b56fSBarry Smith { 21729e0b56fSBarry Smith int ierr; 21829e0b56fSBarry Smith Scalar mone = -1.0; 21929e0b56fSBarry Smith 22029e0b56fSBarry Smith *flag = 0; 22129e0b56fSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 22229e0b56fSBarry Smith ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr); /* y <- y - x */ 22329e0b56fSBarry Smith ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y) */ 22429e0b56fSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 22529e0b56fSBarry Smith return 0; 22629e0b56fSBarry Smith } 22729e0b56fSBarry Smith /* ------------------------------------------------------------------ */ 22829e0b56fSBarry Smith #undef __FUNC__ 2295615d1e5SSatish Balay #define __FUNC__ "SNESCubicLineSearch" 2304b828684SBarry Smith /*@C 231f525115eSLois Curfman McInnes SNESCubicLineSearch - Performs a cubic line search (default line search method). 2325e76c431SBarry Smith 2335e76c431SBarry Smith Input Parameters: 2345e42470aSBarry Smith . snes - nonlinear context 2355e76c431SBarry Smith . x - current iterate 2365e76c431SBarry Smith . f - residual evaluated at x 2375e76c431SBarry Smith . y - search direction (contains new iterate on output) 2385e76c431SBarry Smith . w - work vector 2395e76c431SBarry Smith . fnorm - 2-norm of f 2405e76c431SBarry Smith 241393d2d9aSLois Curfman McInnes Output Parameters: 2425e76c431SBarry Smith . g - residual evaluated at new iterate y 2435e76c431SBarry Smith . y - new iterate (contains search direction on input) 2445e76c431SBarry Smith . gnorm - 2-norm of g 2455e76c431SBarry Smith . ynorm - 2-norm of search length 246761aaf1bSLois Curfman McInnes . flag - 0 if line search succeeds; -1 on failure. 2475e76c431SBarry Smith 248c4a48953SLois Curfman McInnes Options Database Key: 24909d61ba7SLois Curfman McInnes $ -snes_eq_ls cubic 250c4a48953SLois Curfman McInnes 2515e76c431SBarry Smith Notes: 2525e76c431SBarry Smith This line search is taken from "Numerical Methods for Unconstrained 2535e76c431SBarry Smith Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325. 2545e76c431SBarry Smith 25528ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic 25628ae5a21SLois Curfman McInnes 25777c4ece6SBarry Smith .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 2585e76c431SBarry Smith @*/ 2595e42470aSBarry Smith int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w, 260761aaf1bSLois Curfman McInnes double fnorm,double *ynorm,double *gnorm,int *flag) 2615e76c431SBarry Smith { 262406556e6SLois Curfman McInnes /* 263406556e6SLois Curfman McInnes Note that for line search purposes we work with with the related 264406556e6SLois Curfman McInnes minimization problem: 265406556e6SLois Curfman McInnes min z(x): R^n -> R, 266406556e6SLois Curfman McInnes where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2. 267406556e6SLois Curfman McInnes */ 268406556e6SLois Curfman McInnes 269ddd12767SBarry Smith double steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2; 270ea4d3ed3SLois Curfman McInnes double maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg; 2716b5873e3SBarry Smith #if defined(PETSC_COMPLEX) 2725e42470aSBarry Smith Scalar cinitslope, clambda; 2736b5873e3SBarry Smith #endif 2745e42470aSBarry Smith int ierr, count; 2755e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 2765334005bSBarry Smith Scalar mone = -1.0,scale; 2775e76c431SBarry Smith 2787857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 279761aaf1bSLois Curfman McInnes *flag = 0; 2805e76c431SBarry Smith alpha = neP->alpha; 2815e76c431SBarry Smith maxstep = neP->maxstep; 2825e76c431SBarry Smith steptol = neP->steptol; 2835e76c431SBarry Smith 284cddf8d76SBarry Smith ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); 28594a9d846SBarry Smith if (*ynorm == 0.0) { 28694a9d846SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Search direction and size is 0\n"); 287ad922ac9SBarry Smith goto theend1; 28894a9d846SBarry Smith } 2895e76c431SBarry Smith if (*ynorm > maxstep) { /* Step too big, so scale back */ 2905e42470aSBarry Smith scale = maxstep/(*ynorm); 2916b5873e3SBarry Smith #if defined(PETSC_COMPLEX) 29294a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale)); 2936b5873e3SBarry Smith #else 29494a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale); 2956b5873e3SBarry Smith #endif 296393d2d9aSLois Curfman McInnes ierr = VecScale(&scale,y); CHKERRQ(ierr); 2975e76c431SBarry Smith *ynorm = maxstep; 2985e76c431SBarry Smith } 2995e76c431SBarry Smith minlambda = steptol/(*ynorm); 300a703fe33SLois Curfman McInnes ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 3015e42470aSBarry Smith #if defined(PETSC_COMPLEX) 302a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 3035e42470aSBarry Smith initslope = real(cinitslope); 3045e42470aSBarry Smith #else 305a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 3065e42470aSBarry Smith #endif 3075e76c431SBarry Smith if (initslope > 0.0) initslope = -initslope; 3085e76c431SBarry Smith if (initslope == 0.0) initslope = -1.0; 3095e76c431SBarry Smith 310393d2d9aSLois Curfman McInnes ierr = VecCopy(y,w); CHKERRQ(ierr); 3115334005bSBarry Smith ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 31278b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 313cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); 314406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */ 315393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 31694a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Using full step\n"); 317ad922ac9SBarry Smith goto theend1; 3185e76c431SBarry Smith } 3195e76c431SBarry Smith 3205e76c431SBarry Smith /* Fit points with quadratic */ 3215e76c431SBarry Smith lambda = 1.0; count = 0; 322a703fe33SLois Curfman McInnes lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 3235e76c431SBarry Smith lambdaprev = lambda; 3245e76c431SBarry Smith gnormprev = *gnorm; 325ddd12767SBarry Smith if (lambdatemp <= .1*lambda) lambda = .1*lambda; 326ddd12767SBarry Smith else lambda = lambdatemp; 327393d2d9aSLois Curfman McInnes ierr = VecCopy(x,w); CHKERRQ(ierr); 328ea4d3ed3SLois Curfman McInnes lambdaneg = -lambda; 3295e42470aSBarry Smith #if defined(PETSC_COMPLEX) 330ea4d3ed3SLois Curfman McInnes clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 3315e42470aSBarry Smith #else 332ea4d3ed3SLois Curfman McInnes ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr); 3335e42470aSBarry Smith #endif 33478b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 335cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 336406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */ 337393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 338ea4d3ed3SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda); 339ad922ac9SBarry Smith goto theend1; 3405e76c431SBarry Smith } 3415e76c431SBarry Smith 3425e76c431SBarry Smith /* Fit points with cubic */ 3435e76c431SBarry Smith count = 1; 3445e76c431SBarry Smith while (1) { 3455e76c431SBarry Smith if (lambda <= minlambda) { /* bad luck; use full step */ 3462b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch:Unable to find good step length! %d \n",count); 3472b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n", 348ea4d3ed3SLois Curfman McInnes fnorm,*gnorm,*ynorm,lambda,initslope); 349393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 350761aaf1bSLois Curfman McInnes *flag = -1; break; 3515e76c431SBarry Smith } 352406556e6SLois Curfman McInnes t1 = ((*gnorm)*(*gnorm) - fnorm*fnorm)*0.5 - lambda*initslope; 353406556e6SLois Curfman McInnes t2 = (gnormprev*gnormprev - fnorm*fnorm)*0.5 - lambdaprev*initslope; 354ddd12767SBarry Smith a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 3552b022350SLois Curfman McInnes b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 3565e76c431SBarry Smith d = b*b - 3*a*initslope; 3575e76c431SBarry Smith if (d < 0.0) d = 0.0; 3585e76c431SBarry Smith if (a == 0.0) { 3595e76c431SBarry Smith lambdatemp = -initslope/(2.0*b); 3605e76c431SBarry Smith } else { 3615e76c431SBarry Smith lambdatemp = (-b + sqrt(d))/(3.0*a); 3625e76c431SBarry Smith } 3635e76c431SBarry Smith if (lambdatemp > .5*lambda) { 3645e76c431SBarry Smith lambdatemp = .5*lambda; 3655e76c431SBarry Smith } 3665e76c431SBarry Smith lambdaprev = lambda; 3675e76c431SBarry Smith gnormprev = *gnorm; 3685e76c431SBarry Smith if (lambdatemp <= .1*lambda) { 3695e76c431SBarry Smith lambda = .1*lambda; 3705e76c431SBarry Smith } 3715e76c431SBarry Smith else lambda = lambdatemp; 372393d2d9aSLois Curfman McInnes ierr = VecCopy( x, w ); CHKERRQ(ierr); 373ea4d3ed3SLois Curfman McInnes lambdaneg = -lambda; 3745e42470aSBarry Smith #if defined(PETSC_COMPLEX) 375ea4d3ed3SLois Curfman McInnes clambda = lambdaneg; 376393d2d9aSLois Curfman McInnes ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 3775e42470aSBarry Smith #else 378ea4d3ed3SLois Curfman McInnes ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr); 3795e42470aSBarry Smith #endif 38078b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 381cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 382406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* is reduction enough? */ 383393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 384ea4d3ed3SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda); 3852715565aSLois Curfman McInnes goto theend1; 3862b022350SLois Curfman McInnes } else { 3872b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Cubic step no good, shrinking lambda, lambda=%g\n",lambda); 3885e76c431SBarry Smith } 3895e76c431SBarry Smith count++; 3905e76c431SBarry Smith } 391ad922ac9SBarry Smith theend1: 3927857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 3935e42470aSBarry Smith return 0; 3945e76c431SBarry Smith } 39552392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 3965615d1e5SSatish Balay #undef __FUNC__ 3975615d1e5SSatish Balay #define __FUNC__ "SNESQuadraticLineSearch" 3984b828684SBarry Smith /*@C 399f525115eSLois Curfman McInnes SNESQuadraticLineSearch - Performs a quadratic line search. 4005e76c431SBarry Smith 4015e42470aSBarry Smith Input Parameters: 402f59ffdedSLois Curfman McInnes . snes - the SNES context 4035e42470aSBarry Smith . x - current iterate 4045e42470aSBarry Smith . f - residual evaluated at x 4055e42470aSBarry Smith . y - search direction (contains new iterate on output) 4065e42470aSBarry Smith . w - work vector 4075e42470aSBarry Smith . fnorm - 2-norm of f 4085e42470aSBarry Smith 409c4a48953SLois Curfman McInnes Output Parameters: 4105e42470aSBarry Smith . g - residual evaluated at new iterate y 4115e42470aSBarry Smith . y - new iterate (contains search direction on input) 4125e42470aSBarry Smith . gnorm - 2-norm of g 4135e42470aSBarry Smith . ynorm - 2-norm of search length 414761aaf1bSLois Curfman McInnes . flag - 0 if line search succeeds; -1 on failure. 4155e42470aSBarry Smith 416c4a48953SLois Curfman McInnes Options Database Key: 41709d61ba7SLois Curfman McInnes $ -snes_eq_ls quadratic 418c4a48953SLois Curfman McInnes 4195e42470aSBarry Smith Notes: 42077c4ece6SBarry Smith Use SNESSetLineSearch() 421f63b844aSLois Curfman McInnes to set this routine within the SNES_EQ_LS method. 4225e42470aSBarry Smith 423f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, quadratic, line search 424f59ffdedSLois Curfman McInnes 42577c4ece6SBarry Smith .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 4265e42470aSBarry Smith @*/ 4275e42470aSBarry Smith int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 428761aaf1bSLois Curfman McInnes double fnorm, double *ynorm, double *gnorm,int *flag) 4295e76c431SBarry Smith { 430406556e6SLois Curfman McInnes /* 431406556e6SLois Curfman McInnes Note that for line search purposes we work with with the related 432406556e6SLois Curfman McInnes minimization problem: 433406556e6SLois Curfman McInnes min z(x): R^n -> R, 434406556e6SLois Curfman McInnes where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2. 435406556e6SLois Curfman McInnes */ 436ddd12767SBarry Smith double steptol,initslope,lambdaprev,gnormprev,maxstep,minlambda,alpha,lambda,lambdatemp; 4376b5873e3SBarry Smith #if defined(PETSC_COMPLEX) 4385e42470aSBarry Smith Scalar cinitslope,clambda; 4396b5873e3SBarry Smith #endif 4405e42470aSBarry Smith int ierr,count; 4415e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 4425334005bSBarry Smith Scalar mone = -1.0,scale; 4435e76c431SBarry Smith 4447857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 445761aaf1bSLois Curfman McInnes *flag = 0; 4465e42470aSBarry Smith alpha = neP->alpha; 4475e42470aSBarry Smith maxstep = neP->maxstep; 4485e42470aSBarry Smith steptol = neP->steptol; 4495e76c431SBarry Smith 450cddf8d76SBarry Smith VecNorm(y, NORM_2,ynorm ); 45194a9d846SBarry Smith if (*ynorm == 0.0) { 45294a9d846SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n"); 453ad922ac9SBarry Smith goto theend2; 45494a9d846SBarry Smith } 4555e42470aSBarry Smith if (*ynorm > maxstep) { /* Step too big, so scale back */ 4565e42470aSBarry Smith scale = maxstep/(*ynorm); 457393d2d9aSLois Curfman McInnes ierr = VecScale(&scale,y); CHKERRQ(ierr); 4585e42470aSBarry Smith *ynorm = maxstep; 4595e76c431SBarry Smith } 4605e42470aSBarry Smith minlambda = steptol/(*ynorm); 461a703fe33SLois Curfman McInnes ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 4625e42470aSBarry Smith #if defined(PETSC_COMPLEX) 463a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 4645e42470aSBarry Smith initslope = real(cinitslope); 4655e42470aSBarry Smith #else 466a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 4675e42470aSBarry Smith #endif 4685e42470aSBarry Smith if (initslope > 0.0) initslope = -initslope; 4695e42470aSBarry Smith if (initslope == 0.0) initslope = -1.0; 4705e42470aSBarry Smith 471393d2d9aSLois Curfman McInnes ierr = VecCopy(y,w); CHKERRQ(ierr); 4725334005bSBarry Smith ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 47378b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 474cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 475406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */ 476393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 47794a424c1SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n"); 478ad922ac9SBarry Smith goto theend2; 4795e42470aSBarry Smith } 4805e42470aSBarry Smith 4815e42470aSBarry Smith /* Fit points with quadratic */ 4825e42470aSBarry Smith lambda = 1.0; count = 0; 4835e42470aSBarry Smith count = 1; 4845e42470aSBarry Smith while (1) { 4855e42470aSBarry Smith if (lambda <= minlambda) { /* bad luck; use full step */ 48694a424c1SBarry Smith PLogInfo(snes, 4874b828684SBarry Smith "SNESQuadraticLineSearch:Unable to find good step length! %d \n",count); 48894a424c1SBarry Smith PLogInfo(snes, 489ea4d3ed3SLois Curfman McInnes "SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n", 490ea4d3ed3SLois Curfman McInnes fnorm,*gnorm,*ynorm,lambda,initslope); 491393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 492761aaf1bSLois Curfman McInnes *flag = -1; break; 4935e42470aSBarry Smith } 494a703fe33SLois Curfman McInnes lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 4955e42470aSBarry Smith lambdaprev = lambda; 4965e42470aSBarry Smith gnormprev = *gnorm; 4975e42470aSBarry Smith if (lambdatemp <= .1*lambda) { 4985e42470aSBarry Smith lambda = .1*lambda; 4995e42470aSBarry Smith } else lambda = lambdatemp; 500393d2d9aSLois Curfman McInnes ierr = VecCopy(x,w); CHKERRQ(ierr); 5015334005bSBarry Smith lambda = -lambda; 5025e42470aSBarry Smith #if defined(PETSC_COMPLEX) 503393d2d9aSLois Curfman McInnes clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 5045e42470aSBarry Smith #else 505393d2d9aSLois Curfman McInnes ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr); 5065e42470aSBarry Smith #endif 50778b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 508cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 509406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */ 510393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 51194a424c1SBarry Smith PLogInfo(snes, 512ea4d3ed3SLois Curfman McInnes "SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda); 51306259719SBarry Smith break; 5145e42470aSBarry Smith } 5155e42470aSBarry Smith count++; 5165e42470aSBarry Smith } 517ad922ac9SBarry Smith theend2: 5187857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 5195e42470aSBarry Smith return 0; 5205e76c431SBarry Smith } 5215e76c431SBarry Smith /* ------------------------------------------------------------ */ 5225615d1e5SSatish Balay #undef __FUNC__ 5235eea60f9SBarry Smith #define __FUNC__ "SNESSetLineSearch" /* ADIC Ignore */ 524c9e6a524SLois Curfman McInnes /*@C 52577c4ece6SBarry Smith SNESSetLineSearch - Sets the line search routine to be used 526f63b844aSLois Curfman McInnes by the method SNES_EQ_LS. 5275e76c431SBarry Smith 5285e76c431SBarry Smith Input Parameters: 529eafb4bcbSBarry Smith . snes - nonlinear context obtained from SNESCreate() 5305e76c431SBarry Smith . func - pointer to int function 5315e76c431SBarry Smith 532c4a48953SLois Curfman McInnes Available Routines: 533f59ffdedSLois Curfman McInnes . SNESCubicLineSearch() - default line search 534f59ffdedSLois Curfman McInnes . SNESQuadraticLineSearch() - quadratic line search 535f59ffdedSLois Curfman McInnes . SNESNoLineSearch() - the full Newton step (actually not a line search) 5365e76c431SBarry Smith 537c4a48953SLois Curfman McInnes Options Database Keys: 53809d61ba7SLois Curfman McInnes $ -snes_eq_ls [basic,quadratic,cubic] 539912ebf9aSLois Curfman McInnes $ -snes_eq_ls_alpha <alpha> 540912ebf9aSLois Curfman McInnes $ -snes_eq_ls_maxstep <max> 541912ebf9aSLois Curfman McInnes $ -snes_eq_ls_steptol <steptol> 542c4a48953SLois Curfman McInnes 5435e76c431SBarry Smith Calling sequence of func: 544f59ffdedSLois Curfman McInnes func (SNES snes, Vec x, Vec f, Vec g, Vec y, 545761aaf1bSLois Curfman McInnes Vec w, double fnorm, double *ynorm, 546761aaf1bSLois Curfman McInnes double *gnorm, *flag) 5475e76c431SBarry Smith 5485e76c431SBarry Smith Input parameters for func: 5495e42470aSBarry Smith . snes - nonlinear context 5505e76c431SBarry Smith . x - current iterate 5515e76c431SBarry Smith . f - residual evaluated at x 5525e76c431SBarry Smith . y - search direction (contains new iterate on output) 5535e76c431SBarry Smith . w - work vector 5545e76c431SBarry Smith . fnorm - 2-norm of f 5555e76c431SBarry Smith 5565e76c431SBarry Smith Output parameters for func: 5575e76c431SBarry Smith . g - residual evaluated at new iterate y 5585e76c431SBarry Smith . y - new iterate (contains search direction on input) 5595e76c431SBarry Smith . gnorm - 2-norm of g 5605e76c431SBarry Smith . ynorm - 2-norm of search length 561761aaf1bSLois Curfman McInnes . flag - set to 0 if the line search succeeds; a nonzero integer 562761aaf1bSLois Curfman McInnes on failure. 563f59ffdedSLois Curfman McInnes 564f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, set, line search, routine 565f59ffdedSLois Curfman McInnes 566f59ffdedSLois Curfman McInnes .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch() 5675e76c431SBarry Smith @*/ 56877c4ece6SBarry Smith int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec, 569761aaf1bSLois Curfman McInnes double,double*,double*,int*)) 5705e76c431SBarry Smith { 571f63b844aSLois Curfman McInnes if ((snes)->type == SNES_EQ_LS) ((SNES_LS *)(snes->data))->LineSearch = func; 5725e42470aSBarry Smith return 0; 5735e76c431SBarry Smith } 57452392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 5755615d1e5SSatish Balay #undef __FUNC__ 5765eea60f9SBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS" /* ADIC Ignore */ 577f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p) 5785e42470aSBarry Smith { 5795e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 5806daaf66cSBarry Smith 581f63b844aSLois Curfman McInnes PetscPrintf(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n"); 58209d61ba7SLois Curfman McInnes PetscPrintf(snes->comm," %ssnes_eq_ls [basic,quadratic,cubic]\n",p); 58309d61ba7SLois Curfman McInnes PetscPrintf(snes->comm," %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha); 58409d61ba7SLois Curfman McInnes PetscPrintf(snes->comm," %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep); 58509d61ba7SLois Curfman McInnes PetscPrintf(snes->comm," %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol); 5866b5873e3SBarry Smith return 0; 5875e42470aSBarry Smith } 58852392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 5895615d1e5SSatish Balay #undef __FUNC__ 5905eea60f9SBarry Smith #define __FUNC__ "SNESView_EQ_LS" /* ADIC Ignore */ 591f63b844aSLois Curfman McInnes static int SNESView_EQ_LS(PetscObject obj,Viewer viewer) 592a935fc98SLois Curfman McInnes { 593a935fc98SLois Curfman McInnes SNES snes = (SNES)obj; 594a935fc98SLois Curfman McInnes SNES_LS *ls = (SNES_LS *)snes->data; 595d636dbe3SBarry Smith FILE *fd; 59619bcc07fSBarry Smith char *cstr; 59751695f54SLois Curfman McInnes int ierr; 59819bcc07fSBarry Smith ViewerType vtype; 599a935fc98SLois Curfman McInnes 60019bcc07fSBarry Smith ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 60119bcc07fSBarry Smith if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) { 60290ace30eSBarry Smith ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 60319bcc07fSBarry Smith if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch"; 60419bcc07fSBarry Smith else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch"; 60519bcc07fSBarry Smith else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch"; 60619bcc07fSBarry Smith else cstr = "unknown"; 60777c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," line search variant: %s\n",cstr); 60877c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," alpha=%g, maxstep=%g, steptol=%g\n", 609a935fc98SLois Curfman McInnes ls->alpha,ls->maxstep,ls->steptol); 61019bcc07fSBarry Smith } 611a935fc98SLois Curfman McInnes return 0; 612a935fc98SLois Curfman McInnes } 61352392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6145615d1e5SSatish Balay #undef __FUNC__ 6155615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS" 616f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes) 6175e42470aSBarry Smith { 6185e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 6195e42470aSBarry Smith char ver[16]; 6205e42470aSBarry Smith double tmp; 62125cdf11fSBarry Smith int ierr,flg; 6225e42470aSBarry Smith 62309d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr); 62425cdf11fSBarry Smith if (flg) { 6255e42470aSBarry Smith ls->alpha = tmp; 6265e42470aSBarry Smith } 62709d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr); 62825cdf11fSBarry Smith if (flg) { 6295e42470aSBarry Smith ls->maxstep = tmp; 6305e42470aSBarry Smith } 63109d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr); 63225cdf11fSBarry Smith if (flg) { 6335e42470aSBarry Smith ls->steptol = tmp; 6345e42470aSBarry Smith } 63509d61ba7SLois Curfman McInnes ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr); 63625cdf11fSBarry Smith if (flg) { 63748d91487SBarry Smith if (!PetscStrcmp(ver,"basic")) { 63877c4ece6SBarry Smith SNESSetLineSearch(snes,SNESNoLineSearch); 6395e42470aSBarry Smith } 64029e0b56fSBarry Smith else if (!PetscStrcmp(ver,"basicnonorms")) { 64129e0b56fSBarry Smith SNESSetLineSearch(snes,SNESNoLineSearchNoNorms); 64229e0b56fSBarry Smith } 64348d91487SBarry Smith else if (!PetscStrcmp(ver,"quadratic")) { 64477c4ece6SBarry Smith SNESSetLineSearch(snes,SNESQuadraticLineSearch); 6455e42470aSBarry Smith } 64648d91487SBarry Smith else if (!PetscStrcmp(ver,"cubic")) { 64777c4ece6SBarry Smith SNESSetLineSearch(snes,SNESCubicLineSearch); 6485e42470aSBarry Smith } 649e3372554SBarry Smith else {SETERRQ(1,0,"Unknown line search");} 6505e42470aSBarry Smith } 6515e42470aSBarry Smith return 0; 6525e42470aSBarry Smith } 6535e42470aSBarry Smith /* ------------------------------------------------------------ */ 6545615d1e5SSatish Balay #undef __FUNC__ 6555615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS" 656f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES snes ) 6575e42470aSBarry Smith { 6585e42470aSBarry Smith SNES_LS *neP; 6595e42470aSBarry Smith 66029e0b56fSBarry Smith if (snes->method_class != SNES_NONLINEAR_EQUATIONS) SETERRQ(1,0,"For SNES_NONLINEAR_EQUATIONS only"); 661f63b844aSLois Curfman McInnes snes->type = SNES_EQ_LS; 662f63b844aSLois Curfman McInnes snes->setup = SNESSetUp_EQ_LS; 663f63b844aSLois Curfman McInnes snes->solve = SNESSolve_EQ_LS; 664f63b844aSLois Curfman McInnes snes->destroy = SNESDestroy_EQ_LS; 665f63b844aSLois Curfman McInnes snes->converged = SNESConverged_EQ_LS; 666f63b844aSLois Curfman McInnes snes->printhelp = SNESPrintHelp_EQ_LS; 667f63b844aSLois Curfman McInnes snes->setfromoptions = SNESSetFromOptions_EQ_LS; 668f63b844aSLois Curfman McInnes snes->view = SNESView_EQ_LS; 6695baf8537SBarry Smith snes->nwork = 0; 6705e42470aSBarry Smith 6710452661fSBarry Smith neP = PetscNew(SNES_LS); CHKPTRQ(neP); 672ff782a9fSLois Curfman McInnes PLogObjectMemory(snes,sizeof(SNES_LS)); 6735e42470aSBarry Smith snes->data = (void *) neP; 6745e42470aSBarry Smith neP->alpha = 1.e-4; 6755e42470aSBarry Smith neP->maxstep = 1.e8; 6765e42470aSBarry Smith neP->steptol = 1.e-12; 6775e42470aSBarry Smith neP->LineSearch = SNESCubicLineSearch; 6785e42470aSBarry Smith return 0; 6795e42470aSBarry Smith } 6805e42470aSBarry Smith 681