1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*40011551SBarry Smith static char vcid[] = "$Id: ls.c,v 1.100 1998/03/06 00:18:48 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" 13982bf6240SBarry Smith 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" 18782bf6240SBarry Smith 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 */ 446*40011551SBarry Smith double steptol,initslope,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 if (lambdatemp <= .1*lambda) { 5085e42470aSBarry Smith lambda = .1*lambda; 5095e42470aSBarry Smith } else lambda = lambdatemp; 510393d2d9aSLois Curfman McInnes ierr = VecCopy(x,w); CHKERRQ(ierr); 5115334005bSBarry Smith lambda = -lambda; 5123a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 513393d2d9aSLois Curfman McInnes clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 5145e42470aSBarry Smith #else 515393d2d9aSLois Curfman McInnes ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr); 5165e42470aSBarry Smith #endif 51778b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 518cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 519406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */ 520393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 521981c4779SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda); 52206259719SBarry Smith break; 5235e42470aSBarry Smith } 5245e42470aSBarry Smith count++; 5255e42470aSBarry Smith } 526ad922ac9SBarry Smith theend2: 5277857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 5283a40ed3dSBarry Smith PetscFunctionReturn(0); 5295e76c431SBarry Smith } 53082bf6240SBarry Smith 5315e76c431SBarry Smith /* ------------------------------------------------------------ */ 5325615d1e5SSatish Balay #undef __FUNC__ 533d4bb536fSBarry Smith #define __FUNC__ "SNESSetLineSearch" 534c9e6a524SLois Curfman McInnes /*@C 53577c4ece6SBarry Smith SNESSetLineSearch - Sets the line search routine to be used 536f63b844aSLois Curfman McInnes by the method SNES_EQ_LS. 5375e76c431SBarry Smith 5385e76c431SBarry Smith Input Parameters: 539eafb4bcbSBarry Smith . snes - nonlinear context obtained from SNESCreate() 5405e76c431SBarry Smith . func - pointer to int function 5415e76c431SBarry Smith 542c4a48953SLois Curfman McInnes Available Routines: 543f59ffdedSLois Curfman McInnes . SNESCubicLineSearch() - default line search 544f59ffdedSLois Curfman McInnes . SNESQuadraticLineSearch() - quadratic line search 545f59ffdedSLois Curfman McInnes . SNESNoLineSearch() - the full Newton step (actually not a line search) 54682bf6240SBarry Smith . SNESNoLineSearchNoNorms() - use the full Newton step (calculate no norms; faster in parallel) 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 { 58282bf6240SBarry Smith int ierr, (*f)(SNES,int (*f)(SNES,Vec,Vec,Vec,Vec,Vec,double,double*,double*,int*)); 58382bf6240SBarry Smith 5843a40ed3dSBarry Smith PetscFunctionBegin; 58582bf6240SBarry Smith ierr = DLRegisterFind(snes->qlist,"SNESSetLineSearch",(int (**)(void *))&f); CHKERRQ(ierr); 58682bf6240SBarry Smith if (f) { 58782bf6240SBarry Smith ierr = (*f)(snes,func);CHKERRQ(ierr); 58882bf6240SBarry Smith } 5893a40ed3dSBarry Smith PetscFunctionReturn(0); 5905e76c431SBarry Smith } 59182bf6240SBarry Smith 59282bf6240SBarry Smith #undef __FUNC__ 59382bf6240SBarry Smith #define __FUNC__ "SNESSetLineSearch_LS" 59482bf6240SBarry Smith int SNESSetLineSearch_LS(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec, 59582bf6240SBarry Smith double,double*,double*,int*)) 59682bf6240SBarry Smith { 59782bf6240SBarry Smith PetscFunctionBegin; 59882bf6240SBarry Smith ((SNES_LS *)(snes->data))->LineSearch = func; 59982bf6240SBarry Smith PetscFunctionReturn(0); 60082bf6240SBarry Smith } 60182bf6240SBarry Smith 60252392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6035615d1e5SSatish Balay #undef __FUNC__ 604d4bb536fSBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS" 605f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p) 6065e42470aSBarry Smith { 6075e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 6086daaf66cSBarry Smith 6093a40ed3dSBarry Smith PetscFunctionBegin; 61076be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n"); 61176be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls [basic,quadratic,cubic]\n",p); 61276be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha); 61376be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep); 61476be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol); 6153a40ed3dSBarry Smith PetscFunctionReturn(0); 6165e42470aSBarry Smith } 61752392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6185615d1e5SSatish Balay #undef __FUNC__ 619d4bb536fSBarry Smith #define __FUNC__ "SNESView_EQ_LS" 620f63b844aSLois Curfman McInnes static int SNESView_EQ_LS(PetscObject obj,Viewer viewer) 621a935fc98SLois Curfman McInnes { 622a935fc98SLois Curfman McInnes SNES snes = (SNES)obj; 623a935fc98SLois Curfman McInnes SNES_LS *ls = (SNES_LS *)snes->data; 624d636dbe3SBarry Smith FILE *fd; 62519bcc07fSBarry Smith char *cstr; 62651695f54SLois Curfman McInnes int ierr; 62719bcc07fSBarry Smith ViewerType vtype; 628a935fc98SLois Curfman McInnes 6293a40ed3dSBarry Smith PetscFunctionBegin; 63019bcc07fSBarry Smith ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 63119bcc07fSBarry Smith if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) { 63290ace30eSBarry Smith ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 63319bcc07fSBarry Smith if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch"; 63419bcc07fSBarry Smith else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch"; 63519bcc07fSBarry Smith else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch"; 63619bcc07fSBarry Smith else cstr = "unknown"; 63777c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," line search variant: %s\n",cstr); 63877c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," alpha=%g, maxstep=%g, steptol=%g\n", 639a935fc98SLois Curfman McInnes ls->alpha,ls->maxstep,ls->steptol); 64019bcc07fSBarry Smith } 6413a40ed3dSBarry Smith PetscFunctionReturn(0); 642a935fc98SLois Curfman McInnes } 64352392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6445615d1e5SSatish Balay #undef __FUNC__ 6455615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS" 646f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes) 6475e42470aSBarry Smith { 6485e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 6495e42470aSBarry Smith char ver[16]; 6505e42470aSBarry Smith double tmp; 65125cdf11fSBarry Smith int ierr,flg; 6525e42470aSBarry Smith 6533a40ed3dSBarry Smith PetscFunctionBegin; 65409d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr); 65525cdf11fSBarry Smith if (flg) { 6565e42470aSBarry Smith ls->alpha = tmp; 6575e42470aSBarry Smith } 65809d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr); 65925cdf11fSBarry Smith if (flg) { 6605e42470aSBarry Smith ls->maxstep = tmp; 6615e42470aSBarry Smith } 66209d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr); 66325cdf11fSBarry Smith if (flg) { 6645e42470aSBarry Smith ls->steptol = tmp; 6655e42470aSBarry Smith } 66609d61ba7SLois Curfman McInnes ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr); 66725cdf11fSBarry Smith if (flg) { 66848d91487SBarry Smith if (!PetscStrcmp(ver,"basic")) { 66977c4ece6SBarry Smith SNESSetLineSearch(snes,SNESNoLineSearch); 6705e42470aSBarry Smith } 67129e0b56fSBarry Smith else if (!PetscStrcmp(ver,"basicnonorms")) { 67229e0b56fSBarry Smith SNESSetLineSearch(snes,SNESNoLineSearchNoNorms); 67329e0b56fSBarry Smith } 67448d91487SBarry Smith else if (!PetscStrcmp(ver,"quadratic")) { 67577c4ece6SBarry Smith SNESSetLineSearch(snes,SNESQuadraticLineSearch); 6765e42470aSBarry Smith } 67748d91487SBarry Smith else if (!PetscStrcmp(ver,"cubic")) { 67877c4ece6SBarry Smith SNESSetLineSearch(snes,SNESCubicLineSearch); 6795e42470aSBarry Smith } 680a8c6a408SBarry Smith else {SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown line search");} 6815e42470aSBarry Smith } 6823a40ed3dSBarry Smith PetscFunctionReturn(0); 6835e42470aSBarry Smith } 6845e42470aSBarry Smith /* ------------------------------------------------------------ */ 6855615d1e5SSatish Balay #undef __FUNC__ 6865615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS" 687f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES snes ) 6885e42470aSBarry Smith { 68982bf6240SBarry Smith int ierr; 6905e42470aSBarry Smith SNES_LS *neP; 6915e42470aSBarry Smith 6923a40ed3dSBarry Smith PetscFunctionBegin; 693a8c6a408SBarry Smith if (snes->method_class != SNES_NONLINEAR_EQUATIONS) { 694a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only"); 695a8c6a408SBarry Smith } 69682bf6240SBarry Smith 697f63b844aSLois Curfman McInnes snes->setup = SNESSetUp_EQ_LS; 698f63b844aSLois Curfman McInnes snes->solve = SNESSolve_EQ_LS; 699f63b844aSLois Curfman McInnes snes->destroy = SNESDestroy_EQ_LS; 700f63b844aSLois Curfman McInnes snes->converged = SNESConverged_EQ_LS; 701f63b844aSLois Curfman McInnes snes->printhelp = SNESPrintHelp_EQ_LS; 702f63b844aSLois Curfman McInnes snes->setfromoptions = SNESSetFromOptions_EQ_LS; 703f63b844aSLois Curfman McInnes snes->view = SNESView_EQ_LS; 7045baf8537SBarry Smith snes->nwork = 0; 7055e42470aSBarry Smith 7060452661fSBarry Smith neP = PetscNew(SNES_LS); CHKPTRQ(neP); 707ff782a9fSLois Curfman McInnes PLogObjectMemory(snes,sizeof(SNES_LS)); 7085e42470aSBarry Smith snes->data = (void *) neP; 7095e42470aSBarry Smith neP->alpha = 1.e-4; 7105e42470aSBarry Smith neP->maxstep = 1.e8; 7115e42470aSBarry Smith neP->steptol = 1.e-12; 7125e42470aSBarry Smith neP->LineSearch = SNESCubicLineSearch; 71382bf6240SBarry Smith 71482bf6240SBarry Smith ierr = DLRegister(&snes->qlist,"SNESSetLineSearch","SNESSetLineSearch_LS", 71582bf6240SBarry Smith SNESSetLineSearch_LS);CHKERRQ(ierr); 71682bf6240SBarry Smith 7173a40ed3dSBarry Smith PetscFunctionReturn(0); 7185e42470aSBarry Smith } 7195e42470aSBarry Smith 72082bf6240SBarry Smith 72182bf6240SBarry Smith 72282bf6240SBarry Smith 723