1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*e1311b90SBarry Smith static char vcid[] = "$Id: ls.c,v 1.102 1998/03/20 22:52:30 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" 124*e1311b90SBarry Smith int SNESDestroy_EQ_LS(SNES snes) 1255e76c431SBarry Smith { 126393d2d9aSLois Curfman McInnes int ierr; 1273a40ed3dSBarry Smith 1283a40ed3dSBarry Smith PetscFunctionBegin; 1295baf8537SBarry Smith if (snes->nwork) { 1304b0e389bSBarry Smith ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr); 13121c89e3eSBarry Smith } 1320452661fSBarry Smith PetscFree(snes->data); 1333a40ed3dSBarry Smith PetscFunctionReturn(0); 1345e76c431SBarry Smith } 1355e76c431SBarry Smith /* ------------------------------------------------------------ */ 1365615d1e5SSatish Balay #undef __FUNC__ 1375615d1e5SSatish Balay #define __FUNC__ "SNESNoLineSearch" 13882bf6240SBarry Smith 1394b828684SBarry Smith /*@C 1405e42470aSBarry Smith SNESNoLineSearch - This routine is not a line search at all; 1415e76c431SBarry Smith it simply uses the full Newton step. Thus, this routine is intended 1425e76c431SBarry Smith to serve as a template and is not recommended for general use. 1435e76c431SBarry Smith 1445e76c431SBarry Smith Input Parameters: 1455e42470aSBarry Smith . snes - nonlinear context 1465e76c431SBarry Smith . x - current iterate 1475e76c431SBarry Smith . f - residual evaluated at x 1485e76c431SBarry Smith . y - search direction (contains new iterate on output) 1495e76c431SBarry Smith . w - work vector 1505e76c431SBarry Smith . fnorm - 2-norm of f 1515e76c431SBarry Smith 152c4a48953SLois Curfman McInnes Output Parameters: 1535e76c431SBarry Smith . g - residual evaluated at new iterate y 1545e76c431SBarry Smith . y - new iterate (contains search direction on input) 1555e76c431SBarry Smith . gnorm - 2-norm of g 1565e76c431SBarry Smith . ynorm - 2-norm of search length 157761aaf1bSLois Curfman McInnes . flag - set to 0, indicating a successful line search 1585e76c431SBarry Smith 159c4a48953SLois Curfman McInnes Options Database Key: 16009d61ba7SLois Curfman McInnes $ -snes_eq_ls basic 161c4a48953SLois Curfman McInnes 16228ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic 16328ae5a21SLois Curfman McInnes 164f59ffdedSLois Curfman McInnes .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(), 16577c4ece6SBarry Smith SNESSetLineSearch() 1665e76c431SBarry Smith @*/ 1675e42470aSBarry Smith int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 168761aaf1bSLois Curfman McInnes double fnorm, double *ynorm, double *gnorm,int *flag ) 1695e76c431SBarry Smith { 1705e42470aSBarry Smith int ierr; 1715334005bSBarry Smith Scalar mone = -1.0; 1725334005bSBarry Smith 1733a40ed3dSBarry Smith PetscFunctionBegin; 174761aaf1bSLois Curfman McInnes *flag = 0; 1757857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 176cddf8d76SBarry Smith ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); /* ynorm = || y || */ 177ea4d3ed3SLois Curfman McInnes ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr); /* y <- y - x */ 178ea4d3ed3SLois Curfman McInnes ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y) */ 179cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); /* gnorm = || g || */ 1807857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 1813a40ed3dSBarry Smith PetscFunctionReturn(0); 1825e76c431SBarry Smith } 1835e76c431SBarry Smith /* ------------------------------------------------------------------ */ 1845615d1e5SSatish Balay #undef __FUNC__ 18529e0b56fSBarry Smith #define __FUNC__ "SNESNoLineSearchNoNorms" 18682bf6240SBarry Smith 18729e0b56fSBarry Smith /*@C 18829e0b56fSBarry Smith SNESNoLineSearchNoNorms - This routine is not a line search at 18929e0b56fSBarry Smith all; it simply uses the full Newton step. This version does not 19029e0b56fSBarry Smith even compute the norm of the function or search direction; this 19129e0b56fSBarry Smith is intended only when you know the full step is fine and are 19229e0b56fSBarry Smith not checking for convergence of the nonlinear iteration (for 19329e0b56fSBarry Smith example, you are running always for a fixed number of Newton 19429e0b56fSBarry Smith steps). 19529e0b56fSBarry Smith 19629e0b56fSBarry Smith Input Parameters: 19729e0b56fSBarry Smith . snes - nonlinear context 19829e0b56fSBarry Smith . x - current iterate 19929e0b56fSBarry Smith . f - residual evaluated at x 20029e0b56fSBarry Smith . y - search direction (contains new iterate on output) 20129e0b56fSBarry Smith . w - work vector 20229e0b56fSBarry Smith . fnorm - 2-norm of f 20329e0b56fSBarry Smith 20429e0b56fSBarry Smith Output Parameters: 20529e0b56fSBarry Smith . g - residual evaluated at new iterate y 20629e0b56fSBarry Smith . gnorm - not changed 20729e0b56fSBarry Smith . ynorm - not changed 20829e0b56fSBarry Smith . flag - set to 0, indicating a successful line search 20929e0b56fSBarry Smith 21029e0b56fSBarry Smith Options Database Key: 21129e0b56fSBarry Smith $ -snes_eq_ls basicnonorms 21229e0b56fSBarry Smith 21329e0b56fSBarry Smith .keywords: SNES, nonlinear, line search, cubic 21429e0b56fSBarry Smith 21529e0b56fSBarry Smith .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(), 21629e0b56fSBarry Smith SNESSetLineSearch(), SNESNoLineSearch() 21729e0b56fSBarry Smith @*/ 21829e0b56fSBarry Smith int SNESNoLineSearchNoNorms(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 21929e0b56fSBarry Smith double fnorm, double *ynorm, double *gnorm,int *flag ) 22029e0b56fSBarry Smith { 22129e0b56fSBarry Smith int ierr; 22229e0b56fSBarry Smith Scalar mone = -1.0; 22329e0b56fSBarry Smith 2243a40ed3dSBarry Smith PetscFunctionBegin; 22529e0b56fSBarry Smith *flag = 0; 22629e0b56fSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 22729e0b56fSBarry Smith ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr); /* y <- y - x */ 22829e0b56fSBarry Smith ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y) */ 22929e0b56fSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 2303a40ed3dSBarry Smith PetscFunctionReturn(0); 23129e0b56fSBarry Smith } 23229e0b56fSBarry Smith /* ------------------------------------------------------------------ */ 23329e0b56fSBarry Smith #undef __FUNC__ 2345615d1e5SSatish Balay #define __FUNC__ "SNESCubicLineSearch" 2354b828684SBarry Smith /*@C 236f525115eSLois Curfman McInnes SNESCubicLineSearch - Performs a cubic line search (default line search method). 2375e76c431SBarry Smith 2385e76c431SBarry Smith Input Parameters: 2395e42470aSBarry Smith . snes - nonlinear context 2405e76c431SBarry Smith . x - current iterate 2415e76c431SBarry Smith . f - residual evaluated at x 2425e76c431SBarry Smith . y - search direction (contains new iterate on output) 2435e76c431SBarry Smith . w - work vector 2445e76c431SBarry Smith . fnorm - 2-norm of f 2455e76c431SBarry Smith 246393d2d9aSLois Curfman McInnes Output Parameters: 2475e76c431SBarry Smith . g - residual evaluated at new iterate y 2485e76c431SBarry Smith . y - new iterate (contains search direction on input) 2495e76c431SBarry Smith . gnorm - 2-norm of g 2505e76c431SBarry Smith . ynorm - 2-norm of search length 251761aaf1bSLois Curfman McInnes . flag - 0 if line search succeeds; -1 on failure. 2525e76c431SBarry Smith 253c4a48953SLois Curfman McInnes Options Database Key: 25409d61ba7SLois Curfman McInnes $ -snes_eq_ls cubic 255c4a48953SLois Curfman McInnes 2565e76c431SBarry Smith Notes: 2575e76c431SBarry Smith This line search is taken from "Numerical Methods for Unconstrained 2585e76c431SBarry Smith Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325. 2595e76c431SBarry Smith 26028ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic 26128ae5a21SLois Curfman McInnes 26277c4ece6SBarry Smith .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 2635e76c431SBarry Smith @*/ 2645e42470aSBarry Smith int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w, 265761aaf1bSLois Curfman McInnes double fnorm,double *ynorm,double *gnorm,int *flag) 2665e76c431SBarry Smith { 267406556e6SLois Curfman McInnes /* 268406556e6SLois Curfman McInnes Note that for line search purposes we work with with the related 269406556e6SLois Curfman McInnes minimization problem: 270406556e6SLois Curfman McInnes min z(x): R^n -> R, 271406556e6SLois Curfman McInnes where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2. 272406556e6SLois Curfman McInnes */ 273406556e6SLois Curfman McInnes 274ddd12767SBarry Smith double steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2; 275ea4d3ed3SLois Curfman McInnes double maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg; 2763a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 2775e42470aSBarry Smith Scalar cinitslope, clambda; 2786b5873e3SBarry Smith #endif 2795e42470aSBarry Smith int ierr, count; 2805e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 2815334005bSBarry Smith Scalar mone = -1.0,scale; 2825e76c431SBarry Smith 2833a40ed3dSBarry Smith PetscFunctionBegin; 2847857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 285761aaf1bSLois Curfman McInnes *flag = 0; 2865e76c431SBarry Smith alpha = neP->alpha; 2875e76c431SBarry Smith maxstep = neP->maxstep; 2885e76c431SBarry Smith steptol = neP->steptol; 2895e76c431SBarry Smith 290cddf8d76SBarry Smith ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); 291a1c2b6eeSLois Curfman McInnes if (*ynorm < snes->atol) { 292a1c2b6eeSLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Search direction and size are nearly 0\n"); 293a1c2b6eeSLois Curfman McInnes *gnorm = fnorm; 294a1c2b6eeSLois Curfman McInnes ierr = VecCopy(x,y); CHKERRQ(ierr); 295a1c2b6eeSLois Curfman McInnes ierr = VecCopy(f,g); CHKERRQ(ierr); 296ad922ac9SBarry Smith goto theend1; 29794a9d846SBarry Smith } 2985e76c431SBarry Smith if (*ynorm > maxstep) { /* Step too big, so scale back */ 2995e42470aSBarry Smith scale = maxstep/(*ynorm); 3003a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 30194a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale)); 3026b5873e3SBarry Smith #else 30394a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale); 3046b5873e3SBarry Smith #endif 305393d2d9aSLois Curfman McInnes ierr = VecScale(&scale,y); CHKERRQ(ierr); 3065e76c431SBarry Smith *ynorm = maxstep; 3075e76c431SBarry Smith } 3085e76c431SBarry Smith minlambda = steptol/(*ynorm); 309a703fe33SLois Curfman McInnes ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 3103a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 311a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 3125e42470aSBarry Smith initslope = real(cinitslope); 3135e42470aSBarry Smith #else 314a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 3155e42470aSBarry Smith #endif 3165e76c431SBarry Smith if (initslope > 0.0) initslope = -initslope; 3175e76c431SBarry Smith if (initslope == 0.0) initslope = -1.0; 3185e76c431SBarry Smith 319393d2d9aSLois Curfman McInnes ierr = VecCopy(y,w); CHKERRQ(ierr); 3205334005bSBarry Smith ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 32178b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 322cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); 323406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */ 324393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 32594a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Using full step\n"); 326ad922ac9SBarry Smith goto theend1; 3275e76c431SBarry Smith } 3285e76c431SBarry Smith 3295e76c431SBarry Smith /* Fit points with quadratic */ 3305e76c431SBarry Smith lambda = 1.0; count = 0; 331a703fe33SLois Curfman McInnes lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 3325e76c431SBarry Smith lambdaprev = lambda; 3335e76c431SBarry Smith gnormprev = *gnorm; 334ddd12767SBarry Smith if (lambdatemp <= .1*lambda) lambda = .1*lambda; 335ddd12767SBarry Smith else lambda = lambdatemp; 336393d2d9aSLois Curfman McInnes ierr = VecCopy(x,w); CHKERRQ(ierr); 337ea4d3ed3SLois Curfman McInnes lambdaneg = -lambda; 3383a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 339ea4d3ed3SLois Curfman McInnes clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 3405e42470aSBarry Smith #else 341ea4d3ed3SLois Curfman McInnes ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr); 3425e42470aSBarry Smith #endif 34378b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 344cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 345406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */ 346393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 347ea4d3ed3SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda); 348ad922ac9SBarry Smith goto theend1; 3495e76c431SBarry Smith } 3505e76c431SBarry Smith 3515e76c431SBarry Smith /* Fit points with cubic */ 3525e76c431SBarry Smith count = 1; 3535e76c431SBarry Smith while (1) { 3545e76c431SBarry Smith if (lambda <= minlambda) { /* bad luck; use full step */ 3552b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch:Unable to find good step length! %d \n",count); 3562b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n", 357ea4d3ed3SLois Curfman McInnes fnorm,*gnorm,*ynorm,lambda,initslope); 358393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 359761aaf1bSLois Curfman McInnes *flag = -1; break; 3605e76c431SBarry Smith } 361406556e6SLois Curfman McInnes t1 = ((*gnorm)*(*gnorm) - fnorm*fnorm)*0.5 - lambda*initslope; 362406556e6SLois Curfman McInnes t2 = (gnormprev*gnormprev - fnorm*fnorm)*0.5 - lambdaprev*initslope; 363ddd12767SBarry Smith a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 3642b022350SLois Curfman McInnes b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 3655e76c431SBarry Smith d = b*b - 3*a*initslope; 3665e76c431SBarry Smith if (d < 0.0) d = 0.0; 3675e76c431SBarry Smith if (a == 0.0) { 3685e76c431SBarry Smith lambdatemp = -initslope/(2.0*b); 3695e76c431SBarry Smith } else { 3705e76c431SBarry Smith lambdatemp = (-b + sqrt(d))/(3.0*a); 3715e76c431SBarry Smith } 3725e76c431SBarry Smith if (lambdatemp > .5*lambda) { 3735e76c431SBarry Smith lambdatemp = .5*lambda; 3745e76c431SBarry Smith } 3755e76c431SBarry Smith lambdaprev = lambda; 3765e76c431SBarry Smith gnormprev = *gnorm; 3775e76c431SBarry Smith if (lambdatemp <= .1*lambda) { 3785e76c431SBarry Smith lambda = .1*lambda; 3795e76c431SBarry Smith } 3805e76c431SBarry Smith else lambda = lambdatemp; 381393d2d9aSLois Curfman McInnes ierr = VecCopy( x, w ); CHKERRQ(ierr); 382ea4d3ed3SLois Curfman McInnes lambdaneg = -lambda; 3833a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 384ea4d3ed3SLois Curfman McInnes clambda = lambdaneg; 385393d2d9aSLois Curfman McInnes ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 3865e42470aSBarry Smith #else 387ea4d3ed3SLois Curfman McInnes ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr); 3885e42470aSBarry Smith #endif 38978b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 390cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 391406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* is reduction enough? */ 392393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 393ea4d3ed3SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda); 3942715565aSLois Curfman McInnes goto theend1; 3952b022350SLois Curfman McInnes } else { 3962b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Cubic step no good, shrinking lambda, lambda=%g\n",lambda); 3975e76c431SBarry Smith } 3985e76c431SBarry Smith count++; 3995e76c431SBarry Smith } 400ad922ac9SBarry Smith theend1: 4017857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 4023a40ed3dSBarry Smith PetscFunctionReturn(0); 4035e76c431SBarry Smith } 40452392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 4055615d1e5SSatish Balay #undef __FUNC__ 4065615d1e5SSatish Balay #define __FUNC__ "SNESQuadraticLineSearch" 4074b828684SBarry Smith /*@C 408f525115eSLois Curfman McInnes SNESQuadraticLineSearch - Performs a quadratic line search. 4095e76c431SBarry Smith 4105e42470aSBarry Smith Input Parameters: 411f59ffdedSLois Curfman McInnes . snes - the SNES context 4125e42470aSBarry Smith . x - current iterate 4135e42470aSBarry Smith . f - residual evaluated at x 4145e42470aSBarry Smith . y - search direction (contains new iterate on output) 4155e42470aSBarry Smith . w - work vector 4165e42470aSBarry Smith . fnorm - 2-norm of f 4175e42470aSBarry Smith 418c4a48953SLois Curfman McInnes Output Parameters: 4195e42470aSBarry Smith . g - residual evaluated at new iterate y 4205e42470aSBarry Smith . y - new iterate (contains search direction on input) 4215e42470aSBarry Smith . gnorm - 2-norm of g 4225e42470aSBarry Smith . ynorm - 2-norm of search length 423761aaf1bSLois Curfman McInnes . flag - 0 if line search succeeds; -1 on failure. 4245e42470aSBarry Smith 425c4a48953SLois Curfman McInnes Options Database Key: 42609d61ba7SLois Curfman McInnes $ -snes_eq_ls quadratic 427c4a48953SLois Curfman McInnes 4285e42470aSBarry Smith Notes: 42977c4ece6SBarry Smith Use SNESSetLineSearch() 430f63b844aSLois Curfman McInnes to set this routine within the SNES_EQ_LS method. 4315e42470aSBarry Smith 432f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, quadratic, line search 433f59ffdedSLois Curfman McInnes 43477c4ece6SBarry Smith .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 4355e42470aSBarry Smith @*/ 4365e42470aSBarry Smith int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 437761aaf1bSLois Curfman McInnes double fnorm, double *ynorm, double *gnorm,int *flag) 4385e76c431SBarry Smith { 439406556e6SLois Curfman McInnes /* 440406556e6SLois Curfman McInnes Note that for line search purposes we work with with the related 441406556e6SLois Curfman McInnes minimization problem: 442406556e6SLois Curfman McInnes min z(x): R^n -> R, 443406556e6SLois Curfman McInnes where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2. 444406556e6SLois Curfman McInnes */ 44540011551SBarry Smith double steptol,initslope,maxstep,minlambda,alpha,lambda,lambdatemp; 4463a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 4475e42470aSBarry Smith Scalar cinitslope,clambda; 4486b5873e3SBarry Smith #endif 4495e42470aSBarry Smith int ierr,count; 4505e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 4515334005bSBarry Smith Scalar mone = -1.0,scale; 4525e76c431SBarry Smith 4533a40ed3dSBarry Smith PetscFunctionBegin; 4547857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 455761aaf1bSLois Curfman McInnes *flag = 0; 4565e42470aSBarry Smith alpha = neP->alpha; 4575e42470aSBarry Smith maxstep = neP->maxstep; 4585e42470aSBarry Smith steptol = neP->steptol; 4595e76c431SBarry Smith 460cddf8d76SBarry Smith VecNorm(y, NORM_2,ynorm ); 461b37302c6SLois Curfman McInnes if (*ynorm < snes->atol) { 46294a9d846SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n"); 463b37302c6SLois Curfman McInnes *gnorm = fnorm; 464b37302c6SLois Curfman McInnes ierr = VecCopy(x,y); CHKERRQ(ierr); 465b37302c6SLois Curfman McInnes ierr = VecCopy(f,g); CHKERRQ(ierr); 466ad922ac9SBarry Smith goto theend2; 46794a9d846SBarry Smith } 4685e42470aSBarry Smith if (*ynorm > maxstep) { /* Step too big, so scale back */ 4695e42470aSBarry Smith scale = maxstep/(*ynorm); 470393d2d9aSLois Curfman McInnes ierr = VecScale(&scale,y); CHKERRQ(ierr); 4715e42470aSBarry Smith *ynorm = maxstep; 4725e76c431SBarry Smith } 4735e42470aSBarry Smith minlambda = steptol/(*ynorm); 474a703fe33SLois Curfman McInnes ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 4753a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 476a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 4775e42470aSBarry Smith initslope = real(cinitslope); 4785e42470aSBarry Smith #else 479a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 4805e42470aSBarry Smith #endif 4815e42470aSBarry Smith if (initslope > 0.0) initslope = -initslope; 4825e42470aSBarry Smith if (initslope == 0.0) initslope = -1.0; 4835e42470aSBarry Smith 484393d2d9aSLois Curfman McInnes ierr = VecCopy(y,w); CHKERRQ(ierr); 4855334005bSBarry Smith ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 48678b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 487cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 488406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */ 489393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 49094a424c1SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n"); 491ad922ac9SBarry Smith goto theend2; 4925e42470aSBarry Smith } 4935e42470aSBarry Smith 4945e42470aSBarry Smith /* Fit points with quadratic */ 4955e42470aSBarry Smith lambda = 1.0; count = 0; 4965e42470aSBarry Smith count = 1; 4975e42470aSBarry Smith while (1) { 4985e42470aSBarry Smith if (lambda <= minlambda) { /* bad luck; use full step */ 499981c4779SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch:Unable to find good step length! %d \n",count); 500981c4779SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n", 501ea4d3ed3SLois Curfman McInnes fnorm,*gnorm,*ynorm,lambda,initslope); 502393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 503761aaf1bSLois Curfman McInnes *flag = -1; break; 5045e42470aSBarry Smith } 505a703fe33SLois Curfman McInnes lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 5065e42470aSBarry Smith if (lambdatemp <= .1*lambda) { 5075e42470aSBarry Smith lambda = .1*lambda; 5085e42470aSBarry Smith } else lambda = lambdatemp; 509393d2d9aSLois Curfman McInnes ierr = VecCopy(x,w); CHKERRQ(ierr); 5105334005bSBarry Smith lambda = -lambda; 5113a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 512393d2d9aSLois Curfman McInnes clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 5135e42470aSBarry Smith #else 514393d2d9aSLois Curfman McInnes ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr); 5155e42470aSBarry Smith #endif 51678b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 517cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 518406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */ 519393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 520981c4779SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda); 52106259719SBarry Smith break; 5225e42470aSBarry Smith } 5235e42470aSBarry Smith count++; 5245e42470aSBarry Smith } 525ad922ac9SBarry Smith theend2: 5267857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 5273a40ed3dSBarry Smith PetscFunctionReturn(0); 5285e76c431SBarry Smith } 52982bf6240SBarry Smith 5305e76c431SBarry Smith /* ------------------------------------------------------------ */ 5315615d1e5SSatish Balay #undef __FUNC__ 532d4bb536fSBarry Smith #define __FUNC__ "SNESSetLineSearch" 533c9e6a524SLois Curfman McInnes /*@C 53477c4ece6SBarry Smith SNESSetLineSearch - Sets the line search routine to be used 535f63b844aSLois Curfman McInnes by the method SNES_EQ_LS. 5365e76c431SBarry Smith 5375e76c431SBarry Smith Input Parameters: 538eafb4bcbSBarry Smith . snes - nonlinear context obtained from SNESCreate() 5395e76c431SBarry Smith . func - pointer to int function 5405e76c431SBarry Smith 541c4a48953SLois Curfman McInnes Available Routines: 542f59ffdedSLois Curfman McInnes . SNESCubicLineSearch() - default line search 543f59ffdedSLois Curfman McInnes . SNESQuadraticLineSearch() - quadratic line search 544f59ffdedSLois Curfman McInnes . SNESNoLineSearch() - the full Newton step (actually not a line search) 54582bf6240SBarry Smith . SNESNoLineSearchNoNorms() - use the full Newton step (calculate no norms; faster in parallel) 5465e76c431SBarry Smith 547c4a48953SLois Curfman McInnes Options Database Keys: 54809d61ba7SLois Curfman McInnes $ -snes_eq_ls [basic,quadratic,cubic] 549912ebf9aSLois Curfman McInnes $ -snes_eq_ls_alpha <alpha> 550912ebf9aSLois Curfman McInnes $ -snes_eq_ls_maxstep <max> 551912ebf9aSLois Curfman McInnes $ -snes_eq_ls_steptol <steptol> 552c4a48953SLois Curfman McInnes 5535e76c431SBarry Smith Calling sequence of func: 554f59ffdedSLois Curfman McInnes func (SNES snes, Vec x, Vec f, Vec g, Vec y, 555761aaf1bSLois Curfman McInnes Vec w, double fnorm, double *ynorm, 556761aaf1bSLois Curfman McInnes double *gnorm, *flag) 5575e76c431SBarry Smith 5585e76c431SBarry Smith Input parameters for func: 5595e42470aSBarry Smith . snes - nonlinear context 5605e76c431SBarry Smith . x - current iterate 5615e76c431SBarry Smith . f - residual evaluated at x 5625e76c431SBarry Smith . y - search direction (contains new iterate on output) 5635e76c431SBarry Smith . w - work vector 5645e76c431SBarry Smith . fnorm - 2-norm of f 5655e76c431SBarry Smith 5665e76c431SBarry Smith Output parameters for func: 5675e76c431SBarry Smith . g - residual evaluated at new iterate y 5685e76c431SBarry Smith . y - new iterate (contains search direction on input) 5695e76c431SBarry Smith . gnorm - 2-norm of g 5705e76c431SBarry Smith . ynorm - 2-norm of search length 571761aaf1bSLois Curfman McInnes . flag - set to 0 if the line search succeeds; a nonzero integer 572761aaf1bSLois Curfman McInnes on failure. 573f59ffdedSLois Curfman McInnes 574f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, set, line search, routine 575f59ffdedSLois Curfman McInnes 576f59ffdedSLois Curfman McInnes .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch() 5775e76c431SBarry Smith @*/ 57877c4ece6SBarry Smith int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec, 579761aaf1bSLois Curfman McInnes double,double*,double*,int*)) 5805e76c431SBarry Smith { 58182bf6240SBarry Smith int ierr, (*f)(SNES,int (*f)(SNES,Vec,Vec,Vec,Vec,Vec,double,double*,double*,int*)); 58282bf6240SBarry Smith 5833a40ed3dSBarry Smith PetscFunctionBegin; 584*e1311b90SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESSetLineSearch",(void **)&f);CHKERRQ(ierr); 58582bf6240SBarry Smith if (f) { 58682bf6240SBarry Smith ierr = (*f)(snes,func);CHKERRQ(ierr); 58782bf6240SBarry Smith } 5883a40ed3dSBarry Smith PetscFunctionReturn(0); 5895e76c431SBarry Smith } 59082bf6240SBarry Smith 59182bf6240SBarry Smith #undef __FUNC__ 59282bf6240SBarry Smith #define __FUNC__ "SNESSetLineSearch_LS" 59382bf6240SBarry Smith int SNESSetLineSearch_LS(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec, 59482bf6240SBarry Smith double,double*,double*,int*)) 59582bf6240SBarry Smith { 59682bf6240SBarry Smith PetscFunctionBegin; 59782bf6240SBarry Smith ((SNES_LS *)(snes->data))->LineSearch = func; 59882bf6240SBarry Smith PetscFunctionReturn(0); 59982bf6240SBarry Smith } 60082bf6240SBarry Smith 60152392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6025615d1e5SSatish Balay #undef __FUNC__ 603d4bb536fSBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS" 604f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p) 6055e42470aSBarry Smith { 6065e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 6076daaf66cSBarry Smith 6083a40ed3dSBarry Smith PetscFunctionBegin; 60976be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n"); 61076be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls [basic,quadratic,cubic]\n",p); 61176be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha); 61276be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep); 61376be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol); 6143a40ed3dSBarry Smith PetscFunctionReturn(0); 6155e42470aSBarry Smith } 61652392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6175615d1e5SSatish Balay #undef __FUNC__ 618d4bb536fSBarry Smith #define __FUNC__ "SNESView_EQ_LS" 619*e1311b90SBarry Smith static int SNESView_EQ_LS(SNES snes,Viewer viewer) 620a935fc98SLois Curfman McInnes { 621a935fc98SLois Curfman McInnes SNES_LS *ls = (SNES_LS *)snes->data; 622d636dbe3SBarry Smith FILE *fd; 62319bcc07fSBarry Smith char *cstr; 62451695f54SLois Curfman McInnes int ierr; 62519bcc07fSBarry Smith ViewerType vtype; 626a935fc98SLois Curfman McInnes 6273a40ed3dSBarry Smith PetscFunctionBegin; 62819bcc07fSBarry Smith ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 62919bcc07fSBarry Smith if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) { 63090ace30eSBarry Smith ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 63119bcc07fSBarry Smith if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch"; 63219bcc07fSBarry Smith else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch"; 63319bcc07fSBarry Smith else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch"; 63419bcc07fSBarry Smith else cstr = "unknown"; 63577c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," line search variant: %s\n",cstr); 63677c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," alpha=%g, maxstep=%g, steptol=%g\n", 637a935fc98SLois Curfman McInnes ls->alpha,ls->maxstep,ls->steptol); 63819bcc07fSBarry Smith } 6393a40ed3dSBarry Smith PetscFunctionReturn(0); 640a935fc98SLois Curfman McInnes } 64152392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6425615d1e5SSatish Balay #undef __FUNC__ 6435615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS" 644f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes) 6455e42470aSBarry Smith { 6465e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 6475e42470aSBarry Smith char ver[16]; 6485e42470aSBarry Smith double tmp; 64925cdf11fSBarry Smith int ierr,flg; 6505e42470aSBarry Smith 6513a40ed3dSBarry Smith PetscFunctionBegin; 65209d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr); 65325cdf11fSBarry Smith if (flg) { 6545e42470aSBarry Smith ls->alpha = tmp; 6555e42470aSBarry Smith } 65609d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr); 65725cdf11fSBarry Smith if (flg) { 6585e42470aSBarry Smith ls->maxstep = tmp; 6595e42470aSBarry Smith } 66009d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr); 66125cdf11fSBarry Smith if (flg) { 6625e42470aSBarry Smith ls->steptol = tmp; 6635e42470aSBarry Smith } 66409d61ba7SLois Curfman McInnes ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr); 66525cdf11fSBarry Smith if (flg) { 66648d91487SBarry Smith if (!PetscStrcmp(ver,"basic")) { 66777c4ece6SBarry Smith SNESSetLineSearch(snes,SNESNoLineSearch); 6685e42470aSBarry Smith } 66929e0b56fSBarry Smith else if (!PetscStrcmp(ver,"basicnonorms")) { 67029e0b56fSBarry Smith SNESSetLineSearch(snes,SNESNoLineSearchNoNorms); 67129e0b56fSBarry Smith } 67248d91487SBarry Smith else if (!PetscStrcmp(ver,"quadratic")) { 67377c4ece6SBarry Smith SNESSetLineSearch(snes,SNESQuadraticLineSearch); 6745e42470aSBarry Smith } 67548d91487SBarry Smith else if (!PetscStrcmp(ver,"cubic")) { 67677c4ece6SBarry Smith SNESSetLineSearch(snes,SNESCubicLineSearch); 6775e42470aSBarry Smith } 678a8c6a408SBarry Smith else {SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown line search");} 6795e42470aSBarry Smith } 6803a40ed3dSBarry Smith PetscFunctionReturn(0); 6815e42470aSBarry Smith } 6825e42470aSBarry Smith /* ------------------------------------------------------------ */ 6835615d1e5SSatish Balay #undef __FUNC__ 6845615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS" 685f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES snes ) 6865e42470aSBarry Smith { 68782bf6240SBarry Smith int ierr; 6885e42470aSBarry Smith SNES_LS *neP; 6895e42470aSBarry Smith 6903a40ed3dSBarry Smith PetscFunctionBegin; 691a8c6a408SBarry Smith if (snes->method_class != SNES_NONLINEAR_EQUATIONS) { 692a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only"); 693a8c6a408SBarry Smith } 69482bf6240SBarry Smith 695f63b844aSLois Curfman McInnes snes->setup = SNESSetUp_EQ_LS; 696f63b844aSLois Curfman McInnes snes->solve = SNESSolve_EQ_LS; 697f63b844aSLois Curfman McInnes snes->destroy = SNESDestroy_EQ_LS; 698f63b844aSLois Curfman McInnes snes->converged = SNESConverged_EQ_LS; 699f63b844aSLois Curfman McInnes snes->printhelp = SNESPrintHelp_EQ_LS; 700f63b844aSLois Curfman McInnes snes->setfromoptions = SNESSetFromOptions_EQ_LS; 701f63b844aSLois Curfman McInnes snes->view = SNESView_EQ_LS; 7025baf8537SBarry Smith snes->nwork = 0; 7035e42470aSBarry Smith 7040452661fSBarry Smith neP = PetscNew(SNES_LS); CHKPTRQ(neP); 705ff782a9fSLois Curfman McInnes PLogObjectMemory(snes,sizeof(SNES_LS)); 7065e42470aSBarry Smith snes->data = (void *) neP; 7075e42470aSBarry Smith neP->alpha = 1.e-4; 7085e42470aSBarry Smith neP->maxstep = 1.e8; 7095e42470aSBarry Smith neP->steptol = 1.e-12; 7105e42470aSBarry Smith neP->LineSearch = SNESCubicLineSearch; 71182bf6240SBarry Smith 712*e1311b90SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESSetLineSearch","SNESSetLineSearch_LS", 713*e1311b90SBarry Smith (void*)SNESSetLineSearch_LS);CHKERRQ(ierr); 71482bf6240SBarry Smith 7153a40ed3dSBarry Smith PetscFunctionReturn(0); 7165e42470aSBarry Smith } 7175e42470aSBarry Smith 71882bf6240SBarry Smith 71982bf6240SBarry Smith 72082bf6240SBarry Smith 721